逃不掉的自绘标题栏
✨ electron:无边框模式!更漂亮的自绘窗口现在可以使用了! ✨ 现在设置项存储在 LocalStronge 里了 ♿ 移出群聊加了个二次确认 ♿ 优化了复制选中文本的操作体验 🐛 chrome 下滑条无法交互 ➕ 新增依赖 electron-store ➖ 移除依赖 vue3-cookies 🚀 补了一堆构建信息
This commit is contained in:
parent
466e5b0927
commit
cd77da5480
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "stapxs-qq-lite",
|
||||
"version": "2.3.0",
|
||||
"private": true,
|
||||
"private": false,
|
||||
"author": "Stapx Steve [林槐]",
|
||||
"description": "一个兼容 oicq-http 的非官方网页版 QQ 客户端,使用 Vue 重制的全新版本。",
|
||||
"scripts": {
|
||||
|
@ -22,6 +22,7 @@
|
|||
"core-js": "^3.8.3",
|
||||
"date-format": "^4.0.13",
|
||||
"detect-browser": "^5.3.0",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"jquery": "^3.6.0",
|
||||
"js-file-downloader": "^1.1.24",
|
||||
|
@ -40,7 +41,6 @@
|
|||
"vue-gtag-next": "^1.14.0",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
"vue3-cookies": "^1.0.6",
|
||||
"vue3-infinite-scroll-better": "^2.2.0",
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
|
|
59
src/App.vue
59
src/App.vue
|
@ -1,5 +1,14 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<div class="top-bar" v-if="runtimeData.sysConfig.opt_no_window">
|
||||
<img src="img/icons/icon.svg">
|
||||
<span>Stapxs QQ Lite</span>
|
||||
<div class="space"></div>
|
||||
<div class="controller">
|
||||
<div @click="controllWin('minimize')" class="min"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M416 256c0 17.7-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"/></svg></div>
|
||||
<div @click="controllWin('close')" class="close"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M310.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L160 210.7 54.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L114.7 256 9.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L160 301.3 265.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L205.3 256 310.6 150.6z"/></svg></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="base-app">
|
||||
<div class="layui-tab layui-tab-brief main-body">
|
||||
<ul class="layui-tab-title">
|
||||
<li @click="changeTab('主页', 'Home', true)" :class="loginInfo.status ? 'hiden-home' : 'layui-this'">
|
||||
|
@ -239,6 +248,17 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* electron 窗口操作
|
||||
*/
|
||||
controllWin (name: string) {
|
||||
const electron = (process.env.IS_ELECTRON as any) === true ? window.require('electron') : null
|
||||
const reader = electron ? electron.ipcRenderer : null
|
||||
if (reader) {
|
||||
reader.send('win:' + name)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 发起连接
|
||||
*/
|
||||
|
@ -392,24 +412,21 @@ export default defineComponent({
|
|||
// 页面加载完成后
|
||||
window.onload = () => {
|
||||
app.config.globalProperties.$viewer = this.viewerBody
|
||||
const $cookies = app.config.globalProperties.$cookies
|
||||
// 初始化波浪动画
|
||||
runtimeData.tags.loginWaveTimer = this.waveAnimation(document.getElementById('login-wave'))
|
||||
// 加载 cookie 中的保存登陆信息
|
||||
// TODO: 为啥不把登录信息存进设置里 ……
|
||||
if ($cookies.isKey('address')) {
|
||||
this.loginInfo.address = $cookies.get('address')
|
||||
}
|
||||
// 加载设置项
|
||||
runtimeData.sysConfig = Option.load()
|
||||
runtimeData.sysConfig.top_info = $cookies.get('top')
|
||||
// PS:重新再应用一次颜色模式设置模式,因为需要在页面加载完成后处理
|
||||
// 自动暗黑模式需要在暗黑模式之后应用保证可以覆盖它
|
||||
// PS:重新再应用部分需要加载完成后才能应用的设置
|
||||
Option.runAS('opt_dark', Option.get('opt_dark'))
|
||||
Option.runAS('opt_auto_dark', Option.get('opt_auto_dark'))
|
||||
Option.runAS('theme_color', Option.get('theme_color'))
|
||||
Option.runAS('opt_auto_win_color', Option.get('opt_auto_win_color'))
|
||||
if(Option.get('opt_no_window') == true) {
|
||||
const app = document.getElementById('base-app')
|
||||
if(app) app.classList.add('withBar')
|
||||
}
|
||||
// 加载密码保存和自动连接
|
||||
loginInfo.address = runtimeData.sysConfig.address
|
||||
if(runtimeData.sysConfig.save_password && runtimeData.sysConfig.save_password != true) {
|
||||
loginInfo.token = runtimeData.sysConfig.save_password
|
||||
this.tags.savePassword = true
|
||||
|
@ -440,10 +457,10 @@ export default defineComponent({
|
|||
}
|
||||
// 检查版本
|
||||
const appVersion = appInfo.version
|
||||
const cacheVersion = app.config.globalProperties.$cookies.get('version')
|
||||
if (!app.config.globalProperties.$cookies.isKey('version') || cmp(appVersion, cacheVersion) == 1) {
|
||||
const cacheVersion = localStorage.getItem('version')
|
||||
if (!cacheVersion || cmp(appVersion, cacheVersion) == 1) {
|
||||
// 更新 cookie 中的版本信息并抓取更新日志
|
||||
app.config.globalProperties.$cookies.set('version', appVersion, '1m')
|
||||
localStorage.setItem('version', appVersion)
|
||||
logger.debug(this.$t('version_updated') + ': ' + cacheVersion + ' -> ' + appVersion)
|
||||
// 从 Github 获取更新日志
|
||||
const url = 'https://api.github.com/repos/stapxs/stapxs-qq-lite-2.0/commits'
|
||||
|
@ -534,9 +551,10 @@ export default defineComponent({
|
|||
})
|
||||
}
|
||||
// 检查打开次数
|
||||
if ($cookies.isKey('times')) {
|
||||
const getTimes = Number($cookies.get('times')) + 1
|
||||
$cookies.set('times', getTimes, '1m')
|
||||
const times = localStorage.getItem('times')
|
||||
if (times != null) {
|
||||
const getTimes = Number(times) + 1
|
||||
localStorage.setItem('times', getTimes.toString())
|
||||
if (getTimes % 50 == 0) {
|
||||
// 构建 HTML
|
||||
let html = '<div style="display:flex;flex-direction:column;padding:10px 5%;align-items:center;">'
|
||||
|
@ -562,7 +580,7 @@ export default defineComponent({
|
|||
runtimeData.popBoxList.push(popInfo)
|
||||
}
|
||||
} else {
|
||||
$cookies.set('times', 1, '1m')
|
||||
localStorage.setItem('times', '1')
|
||||
// 首次打开,显示首次打开引导信息
|
||||
const popInfo = {
|
||||
template: WelPan,
|
||||
|
@ -586,8 +604,9 @@ export default defineComponent({
|
|||
.then(data => {
|
||||
// 获取已显示过的公告 ID
|
||||
let noticeShow = [] as number[]
|
||||
if ($cookies.isKey('notice_show')) {
|
||||
noticeShow = $cookies.get('notice_show').split(',')
|
||||
const showId = localStorage.getItem('notice_show')
|
||||
if (showId) {
|
||||
noticeShow = showId.split(',').map((id: string) => parseInt(id))
|
||||
}
|
||||
// 解析公告列表
|
||||
data.forEach((notice: any) => {
|
||||
|
@ -621,7 +640,7 @@ export default defineComponent({
|
|||
if (noticeShow.indexOf(notice.id) < 0) {
|
||||
noticeShow.push(notice.id)
|
||||
}
|
||||
$cookies.set('notice_show', noticeShow, '7d')
|
||||
localStorage.setItem('notice_show', noticeShow.toString())
|
||||
// 关闭弹窗
|
||||
runtimeData.popBoxList.shift()
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@ textarea {
|
|||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.chat-pan.withBar {
|
||||
height: calc(100% - 40px);
|
||||
top: 40px;
|
||||
}
|
||||
.chat-pan.full {
|
||||
height: 100%;
|
||||
z-index: 20;
|
||||
|
@ -1270,6 +1274,10 @@ textarea {
|
|||
height: calc(100% - 75px);
|
||||
left: 80px;
|
||||
}
|
||||
.chat-pan.withBar {
|
||||
height: calc(100% - 115px);
|
||||
top: 40px;
|
||||
}
|
||||
.chat-pan.open {
|
||||
transform: translateX(220px);
|
||||
}
|
||||
|
|
|
@ -307,7 +307,7 @@
|
|||
opacity: 0;
|
||||
}
|
||||
.opt-item div.ss-range input::-webkit-slider-runnable-track {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.l10n-info {
|
||||
|
|
|
@ -5,10 +5,69 @@ html, body {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
#app {
|
||||
.top-bar {
|
||||
-webkit-app-region: drag;
|
||||
box-shadow: 0 0 10px 0 rgb(0 0 0 / 28%);
|
||||
background: var(--color-card-2);
|
||||
margin-bottom: 10px;
|
||||
flex-direction: row;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
.top-bar > img {
|
||||
margin: 10px 15px;
|
||||
height: 20px;
|
||||
}
|
||||
.top-bar > span {
|
||||
color: var(--color-font);
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
line-height: 40px;
|
||||
}
|
||||
.top-bar > div.space {
|
||||
flex: 1;
|
||||
}
|
||||
.top-bar > div.controller {
|
||||
-webkit-app-region: no-drag;
|
||||
display: flex;
|
||||
}
|
||||
.top-bar > div.controller > div {
|
||||
transition: background .2s;
|
||||
justify-content: center;
|
||||
border-radius: 7px;
|
||||
display: flex;
|
||||
margin: 4px 1px;
|
||||
padding: 9px;
|
||||
width: 26px;
|
||||
}
|
||||
.top-bar > div.controller > div.min > svg {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
.top-bar > div.controller > div.close {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.top-bar > div.controller > div:hover {
|
||||
background: var(--color-card-1);
|
||||
}
|
||||
.top-bar > div.controller > div.close:hover {
|
||||
background: #f20000dd;
|
||||
}
|
||||
.top-bar > div.controller > div > svg {
|
||||
fill: var(--color-font);
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#app, #base-app {
|
||||
background-color: var(--color-bg);
|
||||
height: 100%;
|
||||
}
|
||||
#base-app.withBar {
|
||||
height: calc(100% - 40px);
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
.main-body {
|
||||
flex-direction: row;
|
||||
|
@ -383,6 +442,9 @@ html, body {
|
|||
padding: 10px;
|
||||
width: 20%;
|
||||
}
|
||||
.menu.topOut {
|
||||
transition: transform .1s, margin-top .1s;
|
||||
}
|
||||
.menu.show {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
|
@ -425,8 +487,6 @@ html, body {
|
|||
display: flex !important;
|
||||
}
|
||||
.ss-range input {
|
||||
-webkit-appearance: none;
|
||||
|
||||
background-image: linear-gradient(var(--color-main), var(--color-main));
|
||||
background-color: var(--color-card-1);
|
||||
background-repeat: no-repeat;
|
||||
|
@ -434,6 +494,8 @@ html, body {
|
|||
background-size: 0% 100%;
|
||||
border-radius: 7px;
|
||||
min-width: 100%;
|
||||
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.ss-range input::-webkit-slider-thumb,
|
||||
.ss-range input::-moz-range-thumb {
|
||||
|
@ -754,6 +816,7 @@ html, body {
|
|||
|
||||
.hiden-home {
|
||||
margin-top: calc(-100% + 5px);
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.qq-err-card {
|
||||
|
@ -882,6 +945,7 @@ html, body {
|
|||
}
|
||||
.hiden-home {
|
||||
margin-top: calc(100% + 5px);
|
||||
transform: translateY(0);
|
||||
margin-left: -70px;
|
||||
}
|
||||
/* 二级侧栏 */
|
||||
|
|
|
@ -273,5 +273,10 @@
|
|||
"option_view_background_blur": "背景模糊",
|
||||
"option_view_background_blur_tip": "什么都看不见了(恼",
|
||||
"pop_chat_image_compression_fail": "压缩图片失败",
|
||||
"pop_chat_image_compression": "正在压缩图片 ……"
|
||||
"pop_chat_image_compression": "正在压缩图片 ……",
|
||||
"chat_msg_menu_remove_tip": "真的要将 {user} 移出群聊吗",
|
||||
"option_view_no_window": "去除窗口框架",
|
||||
"option_view_no_window_tip": "沉浸式没圆角体验(无端",
|
||||
"option_dev_restart": "重启应用",
|
||||
"option_dev_restart_tip": "99% 的特性都能通过重启解决!"
|
||||
}
|
|
@ -1,13 +1,15 @@
|
|||
'use strict'
|
||||
|
||||
import Store from 'electron-store'
|
||||
import windowStateKeeper from 'electron-window-state'
|
||||
import regIpcListener from './function/electron/ipc'
|
||||
import path from 'path'
|
||||
|
||||
import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer'
|
||||
|
||||
import { Menu } from 'electron'
|
||||
import { app, protocol, BrowserWindow } from 'electron'
|
||||
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
|
||||
import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer'
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
|
@ -18,6 +20,7 @@ protocol.registerSchemesAsPrivileged([
|
|||
export let win = undefined as BrowserWindow | undefined
|
||||
|
||||
async function createWindow() {
|
||||
console.log('开始创建窗口 ……')
|
||||
// 窗口创建前事务
|
||||
Menu.setApplicationMenu(null)
|
||||
regIpcListener()
|
||||
|
@ -26,13 +29,16 @@ async function createWindow() {
|
|||
defaultWidth: 1200,
|
||||
defaultHeight: 800
|
||||
})
|
||||
const store = new Store()
|
||||
const noWindow = await store.get('opt_no_window')
|
||||
console.log('窗口框架状态:' + noWindow)
|
||||
win = new BrowserWindow({
|
||||
x: mainWindowState.x,
|
||||
y: mainWindowState.y,
|
||||
width: mainWindowState.width,
|
||||
height: mainWindowState.height,
|
||||
icon: path.join(__dirname,'./public/img/icons/icon.png'),
|
||||
// frame: false,
|
||||
frame: noWindow === true ? false : true,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false
|
||||
|
@ -40,6 +46,7 @@ async function createWindow() {
|
|||
})
|
||||
win.once('focus', () => {if(win)win.flashFrame(false)})
|
||||
mainWindowState.manage(win) // 窗口状态管理器
|
||||
console.log('窗口创建完成')
|
||||
// 加载应用
|
||||
if (process.env.WEBPACK_DEV_SERVER_URL) {
|
||||
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string)
|
||||
|
@ -48,6 +55,7 @@ async function createWindow() {
|
|||
createProtocol('app')
|
||||
win.loadURL('app://./index.html')
|
||||
}
|
||||
console.log('应用加载完成')
|
||||
}
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
|
|
|
@ -196,6 +196,7 @@ export default defineComponent({
|
|||
let style = 'msg-img'
|
||||
// 处理样式
|
||||
// if(isFace) { style += ' face' }
|
||||
if(isFace) { style += ' ' }
|
||||
if(length === 1) { return style += ' alone' }
|
||||
if(at === 0) { return style += ' top' }
|
||||
if(at === length - 1) { return style += ' button' }
|
||||
|
|
|
@ -28,7 +28,6 @@ export class Connector {
|
|||
*/
|
||||
static create(address: string, token?: string) {
|
||||
const $t = app.config.globalProperties.$t
|
||||
const $cookies = app.config.globalProperties.$cookies
|
||||
|
||||
logger.debug($t('log_ws_log_debug'))
|
||||
logger.add(LogType.WS, $t('log_we_log_all'))
|
||||
|
@ -44,7 +43,7 @@ export class Connector {
|
|||
websocket.onopen = () => {
|
||||
logger.add(LogType.WS, $t('log_con_success'))
|
||||
// 保存登录信息(一个月)
|
||||
$cookies.set('address', address, '1m')
|
||||
Option.save('address', address)
|
||||
// 保存密钥
|
||||
if(runtimeData.sysConfig.save_password == true) {
|
||||
Option.save('save_password', token)
|
||||
|
|
|
@ -1,13 +1,33 @@
|
|||
import Store from 'electron-store'
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
|
||||
import { dialog, DownloadItem, ipcMain, shell, systemPreferences } from "electron"
|
||||
import { ipcMain, shell, systemPreferences, app } from "electron"
|
||||
import { GtkTheme, GtkData } from '@jakejarrett/gtk-theme'
|
||||
import { Exception } from 'vue-gtag-next'
|
||||
import { queryKeys } from './util'
|
||||
import { win } from '@/background'
|
||||
|
||||
export default function regIpcListener() {
|
||||
// 关闭窗口
|
||||
ipcMain.on('win:close', () => {
|
||||
if(win) win.close()
|
||||
})
|
||||
// 最小化
|
||||
ipcMain.on('win:minimize', () => {
|
||||
if(win) win.minimize()
|
||||
})
|
||||
// 重启应用
|
||||
ipcMain.on('win:relaunch', () => {
|
||||
app.relaunch()
|
||||
app.exit()
|
||||
})
|
||||
// 单独用于保存窗口框架是否显示的设置
|
||||
// PS:因为改变窗口框架需要在窗口创建前设置,所以单独保存设置便于获取
|
||||
ipcMain.on('opt:saveNoWindow', (event, arg) => {
|
||||
const store = new Store()
|
||||
store.set('opt_no_window', Boolean(arg))
|
||||
})
|
||||
// 获取补充的调试信息
|
||||
ipcMain.handle('opt:getSystemInfo', () => {
|
||||
const systemInfo = {} as { [key: string]: any }
|
||||
|
|
|
@ -791,7 +791,8 @@ function readMemberMessage(data: any) {
|
|||
* @param msg
|
||||
*/
|
||||
function livePackage(msg: any) {
|
||||
//
|
||||
// TODO: 还没写这个功能
|
||||
msg
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,7 +44,16 @@ const configFunction: { [key: string]: (value: any) => void } = {
|
|||
initial_scale: changeInitialScale,
|
||||
msg_type: setMsgType,
|
||||
opt_auto_gtk: updateGTKColor,
|
||||
opt_auto_win_color: updateWinColorOpt
|
||||
opt_auto_win_color: updateWinColorOpt,
|
||||
opt_no_window: changeNoWindow
|
||||
}
|
||||
|
||||
function changeNoWindow(value: boolean) {
|
||||
const electron = (process.env.IS_ELECTRON as any) === true ? window.require('electron') : null
|
||||
const reader = electron ? electron.ipcRenderer : null
|
||||
if(reader) {
|
||||
reader.send('opt:saveNoWindow', value)
|
||||
}
|
||||
}
|
||||
|
||||
function updateWinColorOpt(value: boolean) {
|
||||
|
@ -269,17 +278,24 @@ function changeChatView(name: string | undefined) {
|
|||
*/
|
||||
export function load(): { [key: string]: any } {
|
||||
const options: { [key: string]: any } = {}
|
||||
// 解析拆分 cookie 并执行各个设置项的初始化方法
|
||||
const str: string = app.config.globalProperties.$cookies.get('options')
|
||||
const str = localStorage.getItem('options')
|
||||
if (str != null) {
|
||||
const list = str.split('&')
|
||||
for (let i = 0; i <= list.length; i++) {
|
||||
if (list[i] !== undefined) {
|
||||
const opt: string[] = list[i].split(':')
|
||||
if (opt.length === 2) {
|
||||
// 特殊处理被字符串化的布尔值
|
||||
if (opt[1] === 'true' || opt[1] === 'false') {
|
||||
// 特殊处理被字符串化的布尔值
|
||||
options[opt[0]] = (opt[1] === 'true')
|
||||
} else if(opt[0] == 'top_info') {
|
||||
// 特殊处理 top_info
|
||||
try {
|
||||
options[opt[0]] = JSON.parse(decodeURIComponent(opt[1]))
|
||||
} catch (e) {
|
||||
// 无法解析的数据,初始化为空对象
|
||||
options[opt[0]] = {}
|
||||
}
|
||||
} else {
|
||||
options[opt[0]] = decodeURIComponent(opt[1])
|
||||
}
|
||||
|
@ -335,7 +351,7 @@ export function get(name: string): any {
|
|||
*/
|
||||
export function getRaw(name: string) {
|
||||
// 解析拆分 cookie 并执行各个设置项的初始化方法
|
||||
const str: string = app.config.globalProperties.$cookies.get('options')
|
||||
const str = localStorage.getItem('options')
|
||||
if (str != null) {
|
||||
const list = str.split('&')
|
||||
for (let i = 0; i <= list.length; i++) {
|
||||
|
@ -366,10 +382,12 @@ export function saveAll(config = {} as {[key: string]: any}) {
|
|||
}
|
||||
let str = ''
|
||||
Object.keys(config).forEach(key => {
|
||||
str += key + ':' + encodeURIComponent(config[key]) + '&'
|
||||
const isObject = typeof config[key] == 'object'
|
||||
str += key + ':' +
|
||||
encodeURIComponent(isObject ? JSON.stringify(config[key]) : config[key]) + '&'
|
||||
})
|
||||
str = str.substring(0, str.length - 1)
|
||||
app.config.globalProperties.$cookies.set('options', str, '1m')
|
||||
localStorage.setItem('options', str)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import VueCookies from 'vue3-cookies'
|
||||
import VueViewer from 'v-viewer'
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import InfiniteScroll from 'vue3-infinite-scroll-better'
|
||||
import VueGtag from 'vue-gtag-next'
|
||||
import packageInfo from '../package.json'
|
||||
|
||||
import App from './App.vue'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import { version } from '../package.json'
|
||||
|
||||
import './registerServiceWorker'
|
||||
|
||||
|
@ -38,7 +37,6 @@ export const i18n = createI18n({
|
|||
// 创建 App
|
||||
const app = createApp(App)
|
||||
app.use(i18n)
|
||||
app.use(VueCookies)
|
||||
app.use(VueViewer)
|
||||
app.use(VueClipboard)
|
||||
app.use(InfiniteScroll)
|
||||
|
@ -51,6 +49,6 @@ const strList = ['VERSION', 'WELCOME', 'HELLO']
|
|||
const colorList = ['50534f', 'f9a633', '8076a3', 'f0a1a8', '92aa8a', '606E7A', '7abb7e', 'b573f7', 'ff5370', '99b3db', '677480']
|
||||
const color = colorList[Math.floor(Math.random() * colorList.length)]
|
||||
const str = strList[Math.floor(Math.random() * strList.length)]
|
||||
console.log(`%c${str}%c Stapxs QQ Lite - ${version} ( ${process.env.NODE_ENV} ) `, `font-weight:bold;background:#${color};color:#fff;border-radius:7px 0 0 7px;display:inline-block;padding:7px 14px;margin:7px 0 7px 7px;`, 'background:#fff;color:#000;border-radius:0 7px 7px 0;display:inline-block;padding:7px 14px;margin:7px 7px 7px 0;');
|
||||
console.log(`%c${str}%c Stapxs QQ Lite - ${packageInfo.version} ( ${process.env.NODE_ENV} ) `, `font-weight:bold;background:#${color};color:#fff;border-radius:7px 0 0 7px;display:inline-block;padding:7px 14px;margin:7px 0 7px 7px;`, 'background:#fff;color:#000;border-radius:0 7px 7px 0;display:inline-block;padding:7px 14px;margin:7px 7px 7px 0;');
|
||||
|
||||
console.log(app)
|
|
@ -12,7 +12,7 @@
|
|||
<template>
|
||||
<div
|
||||
:style="`background-image: url(${runtimeData.sysConfig.chat_background})`"
|
||||
:class="'chat-pan' + (runtimeData.tags.openSideBar ? ' open': '')"
|
||||
:class="'chat-pan' + (runtimeData.tags.openSideBar ? ' open': '') + (runtimeData.sysConfig.opt_no_window ? ' withBar': '')"
|
||||
id="chat-pan">
|
||||
<!-- 聊天基本信息 -->
|
||||
<div class="info">
|
||||
|
@ -300,11 +300,11 @@
|
|||
<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg></div>
|
||||
<a>{{ $t('chat_msg_menu_withdraw') }}</a>
|
||||
</div>
|
||||
<div @click="(selectedMsg ? addSpecialMsg({ msgObj: { type: 'at', qq: selectedMsg.sender.user_id }, addText: true }) : '');closeMsgMenu();" v-show="tags.menuDisplay.at">
|
||||
<div @click="(selectedMsg ? addSpecialMsg({ msgObj: { type: 'at', qq: selectedMsg.sender.user_id }, addText: true }) : '');toMainInput();closeMsgMenu();" v-show="tags.menuDisplay.at">
|
||||
<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 64C150 64 64 150 64 256s86 192 192 192c17.7 0 32 14.3 32 32s-14.3 32-32 32C114.6 512 0 397.4 0 256S114.6 0 256 0S512 114.6 512 256v32c0 53-43 96-96 96c-29.3 0-55.6-13.2-73.2-33.9C320 371.1 289.5 384 256 384c-70.7 0-128-57.3-128-128s57.3-128 128-128c27.9 0 53.7 8.9 74.7 24.1c5.7-5 13.1-8.1 21.3-8.1c17.7 0 32 14.3 32 32v80 32c0 17.7 14.3 32 32 32s32-14.3 32-32V256c0-106-86-192-192-192zm64 192c0-35.3-28.7-64-64-64s-64 28.7-64 64s28.7 64 64 64s64-28.7 64-64z"/></svg></div>
|
||||
<a>{{ $t('chat_msg_menu_at') }}</a>
|
||||
</div>
|
||||
<div @click="(selectedMsg ? Connector.send('set_group_kick', {group_id: runtimeData.chatInfo.show.id, user_id: selectedMsg.sender.user_id}, 'setGroupKick') : '');closeMsgMenu();" v-show="tags.menuDisplay.remove">
|
||||
<div @click="removeUser" v-show="tags.menuDisplay.remove">
|
||||
<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L353.3 251.6C407.9 237 448 187.2 448 128C448 57.3 390.7 0 320 0C250.2 0 193.5 55.8 192 125.2L38.8 5.1zM264.3 304.3C170.5 309.4 96 387.2 96 482.3c0 16.4 13.3 29.7 29.7 29.7H514.3c3.9 0 7.6-.7 11-2.1l-261-205.6z"/></svg></div>
|
||||
<a>{{ $t('chat_msg_menu_remove') }}</a>
|
||||
</div>
|
||||
|
@ -621,7 +621,7 @@ export default defineComponent({
|
|||
// 添加 at 信息
|
||||
this.addSpecialMsg({ msgObj: { type: 'at', qq: id }, addText: true })
|
||||
}
|
||||
document.getElementById('main-input')?.focus()
|
||||
this.toMainInput()
|
||||
this.tags.onAtFind = false
|
||||
this.atFindList = null
|
||||
},
|
||||
|
@ -711,11 +711,30 @@ export default defineComponent({
|
|||
}
|
||||
const selection = document.getSelection()
|
||||
const textBody = selection?.anchorNode?.parentElement
|
||||
let textMsg = null as HTMLElement | null
|
||||
// 向外寻找含有 message class 的父元素,直到遇到 chat class
|
||||
let msgParent = textBody
|
||||
if(msgParent) {
|
||||
while(msgParent.className != 'chat') {
|
||||
if(msgParent.className.startsWith('message') &&
|
||||
msgParent.className.indexOf('-') < 0) {
|
||||
textMsg = msgParent
|
||||
break
|
||||
}
|
||||
msgParent = msgParent.parentElement as HTMLDivElement
|
||||
if(!msgParent) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if(textBody && textBody.className.indexOf('msg-text') > -1 &&
|
||||
selection.focusNode == selection.anchorNode) {
|
||||
selection.focusNode == selection.anchorNode &&
|
||||
textMsg && textMsg.id == msg.id) {
|
||||
// 用于判定是否选中了 msg-text 且开始和结束是同一个 Node(防止跨消息复制)
|
||||
this.tags.menuDisplay.copySelect = true
|
||||
this.selectCache = selection.toString()
|
||||
if(this.selectCache.length > 0) {
|
||||
this.tags.menuDisplay.copySelect = true
|
||||
}
|
||||
}
|
||||
const nList = ['xml', 'json']
|
||||
data.message.forEach((item: any) => {
|
||||
|
@ -727,24 +746,30 @@ export default defineComponent({
|
|||
}
|
||||
// 鼠标位置
|
||||
const pointEvent = event as PointerEvent || window.event as PointerEvent
|
||||
const pointX = pointEvent.offsetX
|
||||
const pointX = pointEvent.clientX - msg.getBoundingClientRect().left + 20
|
||||
const pointY = pointEvent.clientY
|
||||
// 移动菜单位置
|
||||
menu.style.marginLeft = pointX + 'px'
|
||||
menu.style.marginTop = pointY + 'px'
|
||||
// 出界判定
|
||||
const menuWidth = menu.clientWidth
|
||||
const menuHeight = menu.clientHeight
|
||||
const msgWidth = msg.offsetWidth
|
||||
const bodyHeight = document.body.clientHeight
|
||||
if (pointX + menuWidth > msgWidth + 27) {
|
||||
menu.style.marginLeft = (msgWidth + 27 - menuWidth) + 'px'
|
||||
}
|
||||
if (pointY + menuHeight > bodyHeight - 10) {
|
||||
menu.style.marginTop = (bodyHeight - menuHeight - 10) + 'px'
|
||||
}
|
||||
// 显示菜单
|
||||
this.tags.showMsgMenu = true
|
||||
// PS:在菜单完全显示出来之前获取不到正确的高度,所以延迟一下
|
||||
setTimeout(() => {
|
||||
// 出界判定
|
||||
const menuHeight = menu.clientHeight
|
||||
const bodyHeight = document.body.clientHeight
|
||||
if (pointY + menuHeight > bodyHeight + 10) {
|
||||
menu.classList.add('topOut')
|
||||
menu.style.marginTop = (bodyHeight - menuHeight - 10) + 'px'
|
||||
// menu.classList.remove('topOut')
|
||||
}
|
||||
}, 90)
|
||||
// 设置消息背景
|
||||
this.tags.openedMenuMsg = msg
|
||||
msg.style.background = '#00000008'
|
||||
|
@ -780,10 +805,7 @@ export default defineComponent({
|
|||
// 显示回复指示器
|
||||
this.tags.isReply = true
|
||||
// 聚焦输入框
|
||||
const mainInput = document.getElementById('main-input')
|
||||
if(mainInput !== null) {
|
||||
mainInput.focus()
|
||||
}
|
||||
this.toMainInput()
|
||||
// 关闭消息菜单
|
||||
if(closeMenu) {
|
||||
this.closeMsgMenu()
|
||||
|
@ -925,6 +947,41 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 移出群聊
|
||||
*/
|
||||
removeUser() {
|
||||
const msg = this.selectedMsg
|
||||
if (msg !== null) {
|
||||
const popInfo = {
|
||||
title: this.$t('popbox_tip'),
|
||||
html: `<span>${this.$t('chat_msg_menu_remove_tip', { user: msg.sender.nickname })}</span>`,
|
||||
button: [
|
||||
{
|
||||
text: app.config.globalProperties.$t('btn_yes'),
|
||||
fun: () => {
|
||||
if(msg) {
|
||||
Connector.send('set_group_kick',
|
||||
{
|
||||
group_id: runtimeData.chatInfo.show.id,
|
||||
user_id: msg.sender.user_id
|
||||
}, 'setGroupKick')
|
||||
this.closeMsgMenu()
|
||||
runtimeData.popBoxList.shift()
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
text: app.config.globalProperties.$t('btn_no'),
|
||||
master: true,
|
||||
fun: () => { runtimeData.popBoxList.shift() }
|
||||
}
|
||||
]
|
||||
}
|
||||
runtimeData.popBoxList.push(popInfo)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取悬浮窗显示位置
|
||||
*/
|
||||
|
|
|
@ -170,6 +170,18 @@
|
|||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<template v-if="runtimeData.tags.isElectron">
|
||||
<div class="opt-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M288 32c0-17.7-14.3-32-32-32s-32 14.3-32 32V256c0 17.7 14.3 32 32 32s32-14.3 32-32V32zM143.5 120.6c13.6-11.3 15.4-31.5 4.1-45.1s-31.5-15.4-45.1-4.1C49.7 115.4 16 181.8 16 256c0 132.5 107.5 240 240 240s240-107.5 240-240c0-74.2-33.8-140.6-86.6-184.6c-13.6-11.3-33.8-9.4-45.1 4.1s-9.4 33.8 4.1 45.1c38.9 32.3 63.5 81 63.5 135.4c0 97.2-78.8 176-176 176s-176-78.8-176-176c0-54.4 24.7-103.1 63.5-135.4z"/></svg>
|
||||
<div>
|
||||
<span>{{ $t('option_dev_restart') }}</span>
|
||||
<span>{{ $t('option_dev_restart_tip') }}</span>
|
||||
</div>
|
||||
<button style="width:100px;font-size:0.8rem;" class="ss-button" @click="restartapp">{{
|
||||
$t('option_dev_runtime_run')
|
||||
}}</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="ss-card">
|
||||
<header>{{ $t('option_dev_backup') }}</header>
|
||||
|
@ -350,9 +362,7 @@ export default defineComponent({
|
|||
try {
|
||||
const json = JSON.parse(input.value)
|
||||
runtimeData.sysConfig = json
|
||||
console.log(json)
|
||||
saveAll(json)
|
||||
app.config.globalProperties.$cookies.set('top', JSON.stringify(json.top_info), '1m')
|
||||
location.reload()
|
||||
} catch (e) {
|
||||
new PopInfo().add(PopType.ERR, app.config.globalProperties.$t('import_config_fail'))
|
||||
|
@ -390,6 +400,13 @@ export default defineComponent({
|
|||
]
|
||||
}
|
||||
runtimeData.popBoxList.push(popInfo)
|
||||
},
|
||||
restartapp() {
|
||||
const electron = (process.env.IS_ELECTRON as any) === true ? window.require('electron') : null
|
||||
const reader = electron ? electron.ipcRenderer : null
|
||||
if (reader) {
|
||||
reader.send('win:relaunch')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import app from '@/main'
|
||||
import Option from '@/function/option'
|
||||
|
||||
import { defineComponent } from 'vue'
|
||||
import { runtimeData } from '@/function/msg'
|
||||
|
@ -141,9 +142,7 @@ export default defineComponent({
|
|||
// 刷新 cookie
|
||||
if (topList) {
|
||||
topInfo[id] = topList
|
||||
runtimeData.sysConfig.top_info = topInfo
|
||||
console.log(topInfo)
|
||||
app.config.globalProperties.$cookies.set('top', JSON.stringify(topInfo), '1m')
|
||||
Option.save('top_info', topInfo)
|
||||
}
|
||||
// 为消息列表内的对象刷新置顶标志
|
||||
for (let i = 0; i < runtimeData.onMsgList.length; i++) {
|
||||
|
|
|
@ -95,10 +95,7 @@
|
|||
</template>
|
||||
<template v-if="runtimeData.tags.isElectron && browser.os == 'Linux'">
|
||||
<div class="opt-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
|
||||
<path
|
||||
d="M192 64C86 64 0 150 0 256S86 448 192 448H384c106 0 192-86 192-192s-86-192-192-192H192zM384 352c-53 0-96-43-96-96s43-96 96-96s96 43 96 96s-43 96-96 96z" />
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M84.6 9.4C72.1-3.1 51.9-3.1 39.4 9.4s-12.5 32.8 0 45.3L120.7 136 28.6 228.1c-37.5 37.5-37.5 98.3 0 135.8L146.1 481.4c37.5 37.5 98.3 37.5 135.8 0L472.3 290.9c28.1-28.1 28.1-73.7 0-101.8L320.9 37.7c-28.1-28.1-73.7-28.1-101.8 0L166 90.7 84.6 9.4zM166 181.3l49.4 49.4c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L211.3 136l53.1-53.1c3.1-3.1 8.2-3.1 11.3 0L427.1 234.3c3.1 3.1 3.1 8.2 0 11.3L384.7 288H65.5c1.4-5.4 4.2-10.4 8.4-14.6L166 181.3z"/></svg>
|
||||
<div>
|
||||
<span>{{ $t('option_view_auto_gtk') }}</span>
|
||||
<span>{{ $t('option_view_auto_gtk_tip') }}</span>
|
||||
|
@ -168,6 +165,22 @@
|
|||
<span :style="`color: var(--color-font${initialScaleShow / 0.05 > 50 ? '-r' : ''})`">{{ initialScaleShow }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="runtimeData.tags.isElectron">
|
||||
<div class="opt-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M384 32C419.3 32 448 60.65 448 96V416C448 451.3 419.3 480 384 480H64C28.65 480 0 451.3 0 416V96C0 60.65 28.65 32 64 32H384zM384 80H64C55.16 80 48 87.16 48 96V416C48 424.8 55.16 432 64 432H384C392.8 432 400 424.8 400 416V96C400 87.16 392.8 80 384 80z"/></svg>
|
||||
<div>
|
||||
<span>{{ $t('option_view_no_window') }}</span>
|
||||
<span>{{ $t('option_view_no_window_tip') }}</span>
|
||||
</div>
|
||||
<label class="ss-switch">
|
||||
<input type="checkbox" @change="save" name="opt_no_window"
|
||||
v-model="runtimeData.sysConfig.opt_no_window">
|
||||
<div>
|
||||
<div></div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -61,18 +61,41 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
pluginOptions: {
|
||||
/**
|
||||
* Electron Builder 设置
|
||||
* @type {import('vue-cli-plugin-electron-builder').PluginOptions}
|
||||
*/
|
||||
electronBuilder: {
|
||||
builderOptions: {
|
||||
nsis: {
|
||||
allowToChangeInstallationDirectory: true,
|
||||
oneClick: false,
|
||||
installerIcon: "./public/favicon.ico",
|
||||
installerHeaderIcon: "./public/favicon.ico"
|
||||
appId: 'com.stapxs.qq-web',
|
||||
productName: 'Stapxs QQ Lite',
|
||||
copyright: 'Copyright © 2022-2023 Stapx Steve [林槐]',
|
||||
|
||||
linux: {
|
||||
target: ['AppImage', 'pacman', 'tar.gz'],
|
||||
maintainer: 'Stapx Steve [林槐]',
|
||||
vendor: 'Stapxs Steve Team',
|
||||
// TODO: 需要完善更完整的尺寸的图标
|
||||
icon: 'public/img/icons/icon.png',
|
||||
synopsis: '一个兼容 oicq-http 的非官方网页版 QQ 客户端。',
|
||||
category: 'Network',
|
||||
// TODO: 将来可能需要占用 QQ 自己的 MIME 类型
|
||||
mimeTypes: ['application/x-stapxs-qq-lite'],
|
||||
desktop: {
|
||||
Type: 'Application',
|
||||
Name: 'Stapxs QQ Lite',
|
||||
GenericName: 'Stapxs QQ Lite Electron 客户端',
|
||||
Comment: '一个兼容 oicq-http 的非官方网页版 QQ 客户端。',
|
||||
Terminal: 'false',
|
||||
Category: 'Network'
|
||||
}
|
||||
},
|
||||
|
||||
win: {
|
||||
icon: './public/favicon.ico'
|
||||
},
|
||||
productName: 'Stapxs QQ Lite'
|
||||
target: 'portable',
|
||||
icon: 'public/img/icons/icon.png',
|
||||
legalTrademarks: 'Copyright © 2022-2023 Stapx Steve [林槐]',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
86
yarn.lock
86
yarn.lock
|
@ -2513,6 +2513,16 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.6.0, ajv@^8.8.0:
|
|||
require-from-string "^2.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@^8.6.3:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
|
||||
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
json-schema-traverse "^1.0.0"
|
||||
require-from-string "^2.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-align@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmmirror.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59"
|
||||
|
@ -2777,6 +2787,11 @@ atob@^2.1.2:
|
|||
resolved "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
atomically@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
|
||||
integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
|
||||
|
||||
autoprefixer@^10.2.4:
|
||||
version "10.4.13"
|
||||
resolved "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8"
|
||||
|
@ -3734,6 +3749,22 @@ concat-stream@^1.5.0:
|
|||
readable-stream "^2.2.2"
|
||||
typedarray "^0.0.6"
|
||||
|
||||
conf@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/conf/-/conf-10.2.0.tgz#838e757be963f1a2386dfe048a98f8f69f7b55d6"
|
||||
integrity sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==
|
||||
dependencies:
|
||||
ajv "^8.6.3"
|
||||
ajv-formats "^2.1.1"
|
||||
atomically "^1.7.0"
|
||||
debounce-fn "^4.0.0"
|
||||
dot-prop "^6.0.1"
|
||||
env-paths "^2.2.1"
|
||||
json-schema-typed "^7.0.3"
|
||||
onetime "^5.1.2"
|
||||
pkg-up "^3.1.0"
|
||||
semver "^7.3.5"
|
||||
|
||||
config-chain@^1.1.11:
|
||||
version "1.1.13"
|
||||
resolved "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4"
|
||||
|
@ -4117,6 +4148,13 @@ date-format@^4.0.13:
|
|||
resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400"
|
||||
integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==
|
||||
|
||||
debounce-fn@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7"
|
||||
integrity sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==
|
||||
dependencies:
|
||||
mimic-fn "^3.0.0"
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
|
@ -4440,6 +4478,13 @@ dot-prop@^5.2.0:
|
|||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dot-prop@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
|
||||
integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==
|
||||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dotenv-expand@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
|
||||
|
@ -4563,6 +4608,14 @@ electron-publish@22.14.13:
|
|||
lazy-val "^1.0.5"
|
||||
mime "^2.5.2"
|
||||
|
||||
electron-store@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-8.1.0.tgz#46a398f2bd9aa83c4a9daaae28380e2b3b9c7597"
|
||||
integrity sha512-2clHg/juMjOH0GT9cQ6qtmIvK183B39ZXR0bUoPwKwYHJsEF3quqyDzMFUAu+0OP8ijmN2CbPRAelhNbWUbzwA==
|
||||
dependencies:
|
||||
conf "^10.2.0"
|
||||
type-fest "^2.17.0"
|
||||
|
||||
electron-to-chromium@^1.4.251:
|
||||
version "1.4.284"
|
||||
resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592"
|
||||
|
@ -4654,7 +4707,7 @@ entities@^2.0.0:
|
|||
resolved "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||
|
||||
env-paths@^2.2.0:
|
||||
env-paths@^2.2.0, env-paths@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.npmmirror.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
|
||||
|
@ -6648,6 +6701,11 @@ json-schema-traverse@^1.0.0:
|
|||
resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
|
||||
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
|
||||
|
||||
json-schema-typed@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9"
|
||||
integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==
|
||||
|
||||
json-schema@0.4.0, json-schema@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
|
||||
|
@ -7173,6 +7231,11 @@ mimic-fn@^2.1.0:
|
|||
resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-fn@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74"
|
||||
integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==
|
||||
|
||||
mimic-response@^1.0.0, mimic-response@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||
|
@ -7958,6 +8021,13 @@ pkg-dir@^4.1.0:
|
|||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
pkg-up@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
|
||||
integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
|
||||
dependencies:
|
||||
find-up "^3.0.0"
|
||||
|
||||
plist@^3.0.1, plist@^3.0.4:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.npmmirror.com/plist/-/plist-3.0.6.tgz#7cfb68a856a7834bca6dbfe3218eb9c7740145d3"
|
||||
|
@ -10137,6 +10207,11 @@ type-fest@^0.8.1:
|
|||
resolved "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
type-fest@^2.17.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
|
||||
integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
|
||||
|
||||
type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
|
@ -10548,19 +10623,12 @@ vue-template-es2015-compiler@^1.9.0:
|
|||
resolved "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
||||
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
||||
|
||||
vue3-cookies@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/vue3-cookies/-/vue3-cookies-1.0.6.tgz#c1da41f1f3d6bbea8e75157d49d09dfc2a18ca8a"
|
||||
integrity sha512-a1UvVD0qIgxyOqjlSOwnLnqAnz8ASltugEv8yX+96i/WGZAN9fEDci7xO4HIWZE1uToUnRq9JnFhvfDCSo45OA==
|
||||
dependencies:
|
||||
vue "^3.0.0"
|
||||
|
||||
vue3-infinite-scroll-better@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmmirror.com/vue3-infinite-scroll-better/-/vue3-infinite-scroll-better-2.2.0.tgz#73a74df93a893fc66e44da2dabd97dbc1139054e"
|
||||
integrity sha512-tIqY7Ab0Hu9j7SiLLNn9jUR2te2THvfVrDvdOfilx/Qk84mc3YS8rjxMNYM5OAlv7Wk92u2HD3rRqx892JafdA==
|
||||
|
||||
vue@^3.0.0, vue@^3.2.13:
|
||||
vue@^3.2.13:
|
||||
version "3.2.45"
|
||||
resolved "https://registry.npmmirror.com/vue/-/vue-3.2.45.tgz#94a116784447eb7dbd892167784619fef379b3c8"
|
||||
integrity sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==
|
||||
|
|
Loading…
Reference in New Issue