diff --git a/capacitor.config.ts b/capacitor.config.ts
index fa581f6f..f8144edb 100644
--- a/capacitor.config.ts
+++ b/capacitor.config.ts
@@ -1,9 +1,14 @@
import type { CapacitorConfig } from '@capacitor/cli'
+
const config: CapacitorConfig = {
appId: 'cn.stapxs.webqq',
appName: 'Stapxs QQ Lite',
- webDir: 'dist'
+ webDir: 'dist',
+ server: {
+ url: 'http://localhost:8080',
+ cleartext: true
+ }
}
export default config
diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj
index af020d64..5a3796d4 100644
--- a/ios/App/App.xcodeproj/project.pbxproj
+++ b/ios/App/App.xcodeproj/project.pbxproj
@@ -349,6 +349,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = LZ4NKVK3NY;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -369,6 +370,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = LZ4NKVK3NY;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
diff --git a/ios/App/App/Info.plist b/ios/App/App/Info.plist
index 40aed8bd..9964c103 100644
--- a/ios/App/App/Info.plist
+++ b/ios/App/App/Info.plist
@@ -3,7 +3,7 @@
CFBundleDevelopmentRegion
- en
+ zh
CFBundleDisplayName
Stapxs QQ Lite
CFBundleExecutable
@@ -45,5 +45,10 @@
UIViewControllerBasedStatusBarAppearance
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+
diff --git a/ios/App/Podfile b/ios/App/Podfile
index 14cdb5b7..1543babe 100644
--- a/ios/App/Podfile
+++ b/ios/App/Podfile
@@ -12,6 +12,7 @@ def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
+ pod 'UntinyCapacitorSafeArea', :path => '../../node_modules/@untiny/capacitor-safe-area'
end
target 'App' do
diff --git a/ios/App/Podfile.lock b/ios/App/Podfile.lock
index 385355b3..8807b25c 100644
--- a/ios/App/Podfile.lock
+++ b/ios/App/Podfile.lock
@@ -4,11 +4,14 @@ PODS:
- CapacitorApp (6.0.2):
- Capacitor
- CapacitorCordova (6.2.0)
+ - UntinyCapacitorSafeArea (1.0.3):
+ - Capacitor
DEPENDENCIES:
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
- "CapacitorApp (from `../../node_modules/@capacitor/app`)"
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"
+ - "UntinyCapacitorSafeArea (from `../../node_modules/@untiny/capacitor-safe-area`)"
EXTERNAL SOURCES:
Capacitor:
@@ -17,12 +20,15 @@ EXTERNAL SOURCES:
:path: "../../node_modules/@capacitor/app"
CapacitorCordova:
:path: "../../node_modules/@capacitor/ios"
+ UntinyCapacitorSafeArea:
+ :path: "../../node_modules/@untiny/capacitor-safe-area"
SPEC CHECKSUMS:
Capacitor: 1f3c7b9802d958cd8c4eb63895fff85dff2e1eea
CapacitorApp: 2a8c3a0b0814322e5e6e15fe595f02c3808f0f8b
CapacitorCordova: b33e7f4aa4ed105dd43283acdd940964374a87d9
+ UntinyCapacitorSafeArea: 6354c662c37e272d587bb2a224cba030d902b2bd
-PODFILE CHECKSUM: 4233f5c5f414604460ff96d372542c311b0fb7a8
+PODFILE CHECKSUM: 3775bab260748c1734d8cf38ed633c5ff6a48b36
COCOAPODS: 1.16.2
diff --git a/package.json b/package.json
index 279d3203..28662f82 100644
--- a/package.json
+++ b/package.json
@@ -12,11 +12,12 @@
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix",
"dev": "vite dev",
"dev:electron": "electron-vite dev",
- "dev:ios": "vite build && capacitor sync && capacitor run ios",
+ "dev:ios": "capacitor sync ios && capacitor run ios",
"build": "vite build",
"build:win": "electron-vite build && electron-builder --win",
"build:mac": "electron-vite build && electron-builder --mac",
- "build:linux": "electron-vite build && electron-builder --linux"
+ "build:linux": "electron-vite build && electron-builder --linux",
+ "build:ios": "vite build && capacitor sync ios && capacitor open ios"
},
"dependencies": {
"@electron-toolkit/preload": "^3.0.0",
@@ -44,6 +45,7 @@
"@stapxs/umami-logger-typescript": "^1.0.12",
"@types/jsonpath": "^0.2.4",
"@types/node": "^20.14.8",
+ "@untiny/capacitor-safe-area": "^1.0.3",
"@vitejs/plugin-vue": "^5.0.5",
"@vue/eslint-config-typescript": "^13.0.0",
"animejs": "^3.2.2",
diff --git a/src/renderer/src/App.vue b/src/renderer/src/App.vue
index dfa8893c..6fce5001 100644
--- a/src/renderer/src/App.vue
+++ b/src/renderer/src/App.vue
@@ -45,24 +45,28 @@
"
@click="changeTab('主页', 'Home', false)">
+ {{ $t('主页') }}
0 ? Option.get('fs_adaptation') : 0) + 'px')
+ }
// 加载密码保存和自动连接
loginInfo.address = runtimeData.sysConfig.address
if (
@@ -509,8 +523,8 @@
* electron 窗口操作
*/
controllWin(name: string) {
- if (runtimeData.reader) {
- runtimeData.reader.send('win:' + name)
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('win:' + name)
}
},
@@ -646,8 +660,8 @@
Connector.send('get_system_msg', {}, 'getSystemMsg')
// 清理通知
- if (runtimeData.reader) {
- runtimeData.reader.send('sys:closeAllNotice', data.id)
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('sys:closeAllNotice', data.id)
}
},
diff --git a/src/renderer/src/assets/css/append/append_ios.css b/src/renderer/src/assets/css/append/append_ios.css
new file mode 100644
index 00000000..4bc9b233
--- /dev/null
+++ b/src/renderer/src/assets/css/append/append_ios.css
@@ -0,0 +1,59 @@
+html {
+ -webkit-tap-highlight-color: transparent;
+}
+
+#app {
+ background: var(--color-card-1);
+}
+.main-body > ul {
+ background: rgba(var(--color-card-rgb), 0.7);
+ backdrop-filter: blur(10px);
+}
+.chat-pan {
+ z-index: 21;
+}
+.chat-pan > div.info > svg {
+ display: none;
+}
+
+.main-body > ul {
+ justify-content: space-evenly;
+}
+.main-body > ul > li > span {
+ display: block !important;
+}
+.hiden-home {
+ margin-left: -140px;
+}
+.main-body > ul > li:first-child {
+ margin-top: 0;
+}
+.main-body > ul > li.active > span,
+.main-body > ul > li.active > svg {
+ background-color: transparent;
+ color: var(--color-main);
+}
+
+.chat-pan > div.chat {
+ margin-bottom: -60px;
+ padding-bottom: 60px;
+}
+.chat-pan > div.chat > div:first-child > div:last-child {
+ padding-bottom: 60px;
+}
+.chat-pan > div.more > div:nth-child(2) {
+ background: rgba(var(--color-card-rgb), 0.7);
+ backdrop-filter: blur(50px);
+}
+.chat-pan > div.more > div:nth-child(2) > div:first-child {
+ border-radius: 999px;
+}
+.chat-pan > div.more > div:nth-child(2) > div:nth-child(2) {
+ background: transparent;
+ border: 1px solid var(--color-font-2);
+ opacity: 0.7;
+ border-radius: 999px;
+}
+.chat-pan > div.more > div:nth-child(2) > div:nth-child(2) > div {
+ display: none;
+}
diff --git a/src/renderer/src/assets/css/chat.css b/src/renderer/src/assets/css/chat.css
index 05352ff6..c0290e6d 100644
--- a/src/renderer/src/assets/css/chat.css
+++ b/src/renderer/src/assets/css/chat.css
@@ -6,8 +6,6 @@ input {
}
.chat-pan {
- --append-fs-adaptation: 0px;
-
background-color: var(--color-card);
background-repeat: no-repeat;
background-position: center;
@@ -18,6 +16,7 @@ input {
pointer-events: none;
transition: all 0.3s;
position: absolute;
+ overflow: hidden;
display: flex;
height: 100%;
left: 371px;
@@ -114,6 +113,9 @@ input {
z-index: 1;
flex: 1;
}
+.chat-pan > div.chat > div {
+ height: calc(100% - var(--append-fs-adaptation));
+}
.chat-pan > div.chat::-webkit-scrollbar {
background: transparent;
}
@@ -392,7 +394,8 @@ input {
.msg-menu {
position: absolute;
overflow: hidden;
- height: 100%;
+ height: calc(100% - var(--append-fs-adaptation)) !important;
+ top: 0;
width: 100%;
z-index: 10;
}
@@ -484,7 +487,7 @@ input {
.mumber-info {
position: absolute;
- height: 100%;
+ height: calc(100% - var(--append-fs-adaptation));
width: 100%;
}
.mumber-info span,
diff --git a/src/renderer/src/assets/css/options.css b/src/renderer/src/assets/css/options.css
index 7ac6b714..97745a33 100644
--- a/src/renderer/src/assets/css/options.css
+++ b/src/renderer/src/assets/css/options.css
@@ -12,12 +12,16 @@
}
.opt-main {
+ overflow: hidden;
background: var(--color-bg);
- height: 100%;
+ height: 0;
flex-direction: row;
display: flex;
padding: 5px;
}
+.opt-main.active {
+ height: 100% !important;
+}
.opt-main > div:first-child {
transition: all 0.3s;
@@ -624,9 +628,6 @@
.option-title {
display: none !important;
}
- .opt-main {
- height: 100%;
- }
.opt-main > div:first-child {
display: none;
}
diff --git a/src/renderer/src/assets/css/view.css b/src/renderer/src/assets/css/view.css
index 8c5c9ae3..9a3597e6 100644
--- a/src/renderer/src/assets/css/view.css
+++ b/src/renderer/src/assets/css/view.css
@@ -98,6 +98,9 @@ textarea:focus {
#app,
#base-app {
+ --append-fs-adaptation: 0;
+
+ overflow: hidden;
height: 100%;
}
#base-app {
@@ -137,6 +140,16 @@ textarea:focus {
display: flex;
justify-content: center;
margin-top: 20px;
+ flex-direction: column;
+}
+.main-body > ul > li > svg {
+ padding-bottom: 10px !important;
+}
+.main-body > ul > li > span {
+ font-size: 0.85rem;
+ text-align: center;
+ color: var(--color-font);
+ display: none;
}
.main-body > ul > li:first-child {
margin-top: 10px;
@@ -276,6 +289,7 @@ textarea:focus {
}
.friend-view {
+ overflow: hidden;
flex-direction: row;
user-select: text;
display: flex;
@@ -311,6 +325,9 @@ textarea:focus {
display: flex;
width: 300px;
}
+.friend-list .small {
+ display: none;
+}
.friend-list > div:first-child {
margin: 15px;
}
@@ -355,7 +372,6 @@ textarea:focus {
align-items: center;
display: flex;
width: 100%;
- margin-top: 10px;
background: var(--color-card-2);
border-bottom: 1px solid var(--color-font-2);
border-radius: 7px;
@@ -1080,10 +1096,13 @@ textarea:focus {
/* 二级侧栏 */
.friend-list {
transition: width 0.3s;
- width: 80px !important;
+ width: 80px;
}
.friend-list.open {
- width: 300px !important;
+ width: 300px;
+ }
+ .friend-list.open .small {
+ display: flex;
}
.friend-list > div:first-child > div.base {
display: none;
@@ -1141,6 +1160,12 @@ textarea:focus {
.friend-list > div:last-child.open > div.list > div > div > div {
display: block;
}
+ .friend-list > div:first-child > div.small > span {
+ display: none;
+ }
+ .friend-list.open > div:first-child > div.small > span {
+ display: flex;
+ }
.friend-body {
background: transparent !important;
justify-content: center;
@@ -1206,10 +1231,35 @@ textarea:focus {
display: none;
}
/* 二级侧栏 */
- .friend-list.open {
+ .friend-list {
width: 100% !important;
}
- .friend-list-space.open {
+ .friend-list .small {
+ display: flex !important;
+ }
+ .friend-body > div {
+ display: block !important;
+ }
+ .friend-view > div:last-child {
+ display: none !important;
+ }
+ .friend-list > div:last-child > div:not(.list),
+ .friend-list > div:last-child > div.list > div > div {
+ padding: 10px !important;
+ margin: 10px !important;
+ }
+ .friend-list > div:first-child > div.small > div {
+ display: none;
+ }
+ .friend-list > div:first-child > div.small > span {
+ display: flex !important;
+ margin-right: 0;
+ }
+ .friend-list > div:first-child > div.small > div.reload,
+ .friend-list > div:first-child > div.small > label {
+ display: flex !important;
+ }
+ .friend-list-space {
overflow: hidden;
width: 0;
}
diff --git a/src/renderer/src/components/NoticeBody.vue b/src/renderer/src/components/NoticeBody.vue
index 35a8e680..2b142591 100644
--- a/src/renderer/src/components/NoticeBody.vue
+++ b/src/renderer/src/components/NoticeBody.vue
@@ -83,7 +83,7 @@
height: number
} | null
if (runtimeData.tags.isElectron) {
- const reader = runtimeData.reader
+ const reader = runtimeData.plantform.reader
if (reader) {
windowInfo = await reader.invoke('win:getWindowInfo')
}
@@ -182,7 +182,7 @@
num = Math.round(num)
// 输出 translateX
if (runtimeData.tags.isElectron && windowInfo) {
- const reader = runtimeData.reader
+ const reader = runtimeData.plantform.reader
if (reader) {
reader.send('win:move', {
x: windowInfo.x + num,
diff --git a/src/renderer/src/function/base.ts b/src/renderer/src/function/base.ts
index 5622322d..7dac6db7 100644
--- a/src/renderer/src/function/base.ts
+++ b/src/renderer/src/function/base.ts
@@ -78,21 +78,25 @@ export class Logger {
*/
private print(type: LogType, args: string, data: any, hidden: boolean) {
const error = new Error()
+ // 浏览器类型,用于判断是不是 webkit
+ const isWebkit = /webkit/i.test(navigator.userAgent)
// 从调用栈中获取调用者信息
let from = undefined as string | undefined
const stack = error.stack
if (stack) {
const stackArr = stack.split('\n')
- // 找到第一个不是 at Logger 开头的调用者信息
+ // 找到第一个不是 at Logger 开头的调用者信息(WebKit 为第一个 @ 开头)
for (let i = 1; i < stackArr.length; i++) {
- if (!stackArr[i].includes('at Logger')) {
+ if (isWebkit ? stackArr[i].startsWith('@') : !stackArr[i].includes('at Logger')) {
// 取出链接部分,去除括号
- from =
- stackArr[i].replace(/\(|\)/g, '').split(' ').pop() || ''
+ from = stackArr[i].replace(/\(|\)/g, '').split(' ').pop() || ''
from = from.replace(
'webpack-internal:///./',
'webpack-internal:///',
)
+ if(from.startsWith('@')) {
+ from = from.substring(1)
+ }
if (from.startsWith('webpack-internal:///node_modules')) {
from = undefined
}
@@ -119,7 +123,7 @@ export class Logger {
`background:#${this.logTypeInfo[type][0]};color:#${this.logTypeInfo[type][1]};border-radius:7px 0 0 7px;padding:2px 4px 2px 7px;margin-bottom:7px;`,
'background:#e3e8ec;color:#000;padding:2px 7px 4px 4px;border-radius:0 7px 7px 0;margin-bottom:7px;',
'',
- data,
+ data
)
} else {
// eslint-disable-next-line no-console
@@ -127,7 +131,7 @@ export class Logger {
`%c${typeStr}%c ${args}`,
`background:#${this.logTypeInfo[type][0]};color:#${this.logTypeInfo[type][1]};border-radius:7px;padding:2px 4px 2px 7px;margin-bottom:7px;`,
'',
- data,
+ data
)
}
}
diff --git a/src/renderer/src/function/connect.ts b/src/renderer/src/function/connect.ts
index 6c960eb9..2cb55c0f 100644
--- a/src/renderer/src/function/connect.ts
+++ b/src/renderer/src/function/connect.ts
@@ -39,7 +39,7 @@ export class Connector {
// Electron 默认使用后端连接模式
if (runtimeData.tags.isElectron) {
logger.add(LogType.WS, '使用后端连接模式')
- const reader = runtimeData.reader
+ const reader = runtimeData.plantform.reader
if (reader) {
reader.send('onebot:connect', {
address: address,
@@ -183,7 +183,7 @@ export class Connector {
*/
static close() {
if (runtimeData.tags.isElectron) {
- const reader = runtimeData.reader
+ const reader = runtimeData.plantform.reader
if (reader) {
reader.send('onebot:close')
}
@@ -218,7 +218,7 @@ export class Connector {
static sendRaw(json: string) {
// 发送
if (runtimeData.tags.isElectron) {
- const reader = runtimeData.reader
+ const reader = runtimeData.plantform.reader
if (reader) {
reader.send('onebot:send', json)
}
diff --git a/src/renderer/src/function/elements/information.ts b/src/renderer/src/function/elements/information.ts
index 617364a0..dd64641e 100644
--- a/src/renderer/src/function/elements/information.ts
+++ b/src/renderer/src/function/elements/information.ts
@@ -7,7 +7,6 @@ export enum BotMsgType {
}
export interface RunTimeDataElem {
- reader?: IpcRenderer | null
sysConfig: { [key: string]: any }
jsonMap?: any
botInfo: { [key: string]: any }
@@ -21,6 +20,11 @@ export interface RunTimeDataElem {
chatView: any
msgView: any
}
+ plantform: {
+ reader?: IpcRenderer | null,
+ capacitor?: any,
+ pulgins?: any
+ },
tags: {
firstLoad: boolean
msgType: BotMsgType
diff --git a/src/renderer/src/function/msg.ts b/src/renderer/src/function/msg.ts
index ccd462b2..99e2c2a0 100644
--- a/src/renderer/src/function/msg.ts
+++ b/src/renderer/src/function/msg.ts
@@ -1674,8 +1674,8 @@ function newMsg(_: string, data: any) {
new Notify().notify(msgInfo)
}
// MacOS:刷新 touchbar
- if (runtimeData.tags.isElectron && runtimeData.reader) {
- runtimeData.reader.send('sys:newMessage', {
+ if (runtimeData.tags.isElectron && runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('sys:newMessage', {
id: id,
image: msgInfo.icon,
name: msgInfo.title,
@@ -1747,6 +1747,7 @@ function updateSysInfo(
// ==============================================================
const baseRuntime = {
+ plantform: {} as any,
tags: {
firstLoad: false,
canLoadHistory: true,
@@ -1754,6 +1755,7 @@ const baseRuntime = {
viewer: { index: 0 },
msgType: BotMsgType.Array,
isElectron: false,
+ isCapacitor: false,
platform: undefined,
release: undefined,
connectSsl: false,
diff --git a/src/renderer/src/function/notify.ts b/src/renderer/src/function/notify.ts
index 7c29fbba..d2295cb0 100644
--- a/src/renderer/src/function/notify.ts
+++ b/src/renderer/src/function/notify.ts
@@ -32,8 +32,8 @@ export class Notify {
}
// 发送消息
if (isElectron) {
- if (runtimeData.reader)
- runtimeData.reader.send('sys:sendNotice', info)
+ if (runtimeData.plantform.reader)
+ runtimeData.plantform.reader.send('sys:sendNotice', info)
} else {
// Safari:在 iOS 下,如果页面没有被创建为主屏幕,通知无法被调用
// 最见鬼的是它不是方法返回失败,而且整个 Notification 对象都没有
@@ -61,8 +61,8 @@ export class Notify {
public notifySingle(info: NotifyInfo) {
const isElectron = runtimeData.tags.isElectron
if (isElectron) {
- if (runtimeData.reader)
- runtimeData.reader.send('sys:sendNotice', info)
+ if (runtimeData.plantform.reader)
+ runtimeData.plantform.reader.send('sys:sendNotice', info)
} else {
// Safari:在 iOS 下,如果页面没有被创建为主屏幕,通知无法被调用
// 最见鬼的是它不是方法返回失败,而且整个 Notification 对象都没有
@@ -90,8 +90,8 @@ export class Notify {
public closeAll(userId: string) {
const isElectron = runtimeData.tags.isElectron
if (isElectron) {
- if (runtimeData.reader)
- runtimeData.reader.send('sys:closeAllNotice', userId)
+ if (runtimeData.plantform.reader)
+ runtimeData.plantform.reader.send('sys:closeAllNotice', userId)
} else {
const keys = Object.keys(Notify.notifyList)
keys.forEach((key) => {
@@ -109,7 +109,7 @@ export class Notify {
public clear() {
const isElectron = runtimeData.tags.isElectron
if (isElectron) {
- if (runtimeData.reader) runtimeData.reader.send('sys:clearNotice')
+ if (runtimeData.plantform.reader) runtimeData.plantform.reader.send('sys:clearNotice')
} else {
const keys = Object.keys(Notify.notifyList)
keys.forEach((key) => {
@@ -127,8 +127,8 @@ export class Notify {
private close(tag: string) {
const isElectron = runtimeData.tags.isElectron
if (isElectron) {
- if (runtimeData.reader)
- runtimeData.reader.send('sys:closeNotice', tag)
+ if (runtimeData.plantform.reader)
+ runtimeData.plantform.reader.send('sys:closeNotice', tag)
} else {
Notify.notifyList[tag]?.close()
}
diff --git a/src/renderer/src/function/option.ts b/src/renderer/src/function/option.ts
index 45a93e33..cd4bfa60 100644
--- a/src/renderer/src/function/option.ts
+++ b/src/renderer/src/function/option.ts
@@ -60,8 +60,8 @@ const configFunction: { [key: string]: (value: any) => void } = {
}
function viewAlwaysTop(value: boolean) {
- if (runtimeData.reader) {
- runtimeData.reader.send('win:alwaysTop', value)
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('win:alwaysTop', value)
}
}
@@ -81,8 +81,8 @@ function viewRevolve(value: boolean) {
function updateWinColorOpt(value: boolean) {
if (value == true) {
- if (runtimeData.reader) {
- runtimeData.reader.on('sys:WinColorChanged', (_, params) => {
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.on('sys:WinColorChanged', (_, params) => {
updateWinColor(params)
})
}
@@ -304,8 +304,8 @@ function changeChatView(name: string | undefined) {
export function load(): { [key: string]: any } {
let data = {} as { [key: string]: any }
- if (runtimeData.reader) {
- data = runtimeData.reader.sendSync('opt:getAll')
+ if (runtimeData.plantform.reader) {
+ data = runtimeData.plantform.reader.sendSync('opt:getAll')
} else {
const str = localStorage.getItem('options')
if (str != null) {
@@ -392,8 +392,8 @@ export function get(name: string): any {
* @returns 设置项值(如果没有则为 null)
*/
export function getRaw(name: string) {
- if (runtimeData.reader) {
- return runtimeData.reader.sendSync('opt:get', name)
+ if (runtimeData.plantform.reader) {
+ return runtimeData.plantform.reader.sendSync('opt:get', name)
} else {
// 解析拆分 cookie 并执行各个设置项的初始化方法
const str = localStorage.getItem('options')
@@ -441,7 +441,7 @@ export function saveAll(config = {} as { [key: string]: any }) {
localStorage.setItem('options', str)
// electron:将配置保存
- if (runtimeData.reader) {
+ if (runtimeData.plantform.reader) {
const saveConfig = config
Object.keys(config).forEach((key) => {
const isObject = typeof config[key] == 'object'
@@ -449,7 +449,7 @@ export function saveAll(config = {} as { [key: string]: any }) {
? JSON.stringify(config[key])
: config[key]
})
- runtimeData.reader.send('opt:saveAll', saveConfig)
+ runtimeData.plantform.reader.send('opt:saveAll', saveConfig)
}
}
@@ -521,8 +521,8 @@ export function runASWEvent(event: Event) {
text: app.config.globalProperties.$t('确定'),
fun: () => {
if (runtimeData.tags.isElectron) {
- if (runtimeData.reader) {
- runtimeData.reader.send('win:relaunch')
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('win:relaunch')
}
} else {
location.reload()
diff --git a/src/renderer/src/function/utils/appUtil.ts b/src/renderer/src/function/utils/appUtil.ts
index 85870e7a..a2d34d9b 100644
--- a/src/renderer/src/function/utils/appUtil.ts
+++ b/src/renderer/src/function/utils/appUtil.ts
@@ -248,11 +248,11 @@ export function downloadFile(
logger.error(e as Error, '下载文件失败')
}
} else {
- if (runtimeData.reader) {
- runtimeData.reader.on('sys:downloadBack', (_, params) => {
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.on('sys:downloadBack', (_, params) => {
onprocess(params)
})
- runtimeData.reader.send('sys:download', {
+ runtimeData.plantform.reader.send('sys:download', {
downloadPath: url,
fileName: name,
})
@@ -261,9 +261,9 @@ export function downloadFile(
}
export async function loadWinColor() {
- if (runtimeData.reader) {
+ if (runtimeData.plantform.reader) {
// 获取系统主题色
- updateWinColor(await runtimeData.reader.invoke('sys:getWinColor'))
+ updateWinColor(await runtimeData.plantform.reader.invoke('sys:getWinColor'))
}
}
@@ -308,7 +308,7 @@ export function updateWinColor(color: string) {
export function createMenu() {
const { $t } = app.config.globalProperties
// MacOS:初始化菜单
- if (runtimeData.reader) {
+ if (runtimeData.plantform.reader) {
// 初始化菜单
const menuTitles = {} as { [key: string]: string }
menuTitles.success = $t(
@@ -347,31 +347,31 @@ export function createMenu() {
menuTitles.feedback = $t('在 Github 上反馈问题')
menuTitles.license = $t('许可协议')
- runtimeData.reader.send('sys:createMenu', menuTitles)
+ runtimeData.plantform.reader.send('sys:createMenu', menuTitles)
}
}
export function updateMenu(config: { id: string; action: string; value: any }) {
// MacOS:更新菜单
- if (runtimeData.reader) {
- runtimeData.reader.send('sys:updateMenu', config)
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('sys:updateMenu', config)
}
}
export function createIpc() {
- if (runtimeData.reader) {
- runtimeData.reader.on('bot:flushUser', () => {
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.on('bot:flushUser', () => {
reloadUsers()
popInfo.add(
PopType.INFO,
app.config.globalProperties.$t('刷新用户列表成功'),
)
})
- runtimeData.reader.on('bot:logout', () => {
+ runtimeData.plantform.reader.on('bot:logout', () => {
option.remove('auto_connect')
Connector.close()
})
- runtimeData.reader.on('bot:quickReply', (_, data) => {
+ runtimeData.plantform.reader.on('bot:quickReply', (_, data) => {
sendMsgRaw(
data.id,
data.type,
@@ -394,10 +394,10 @@ export function createIpc() {
}
})
- runtimeData.reader.on('sys:handleUri', (_, data) => {
+ runtimeData.plantform.reader.on('sys:handleUri', (_, data) => {
logger.info(JSON.stringify(data))
})
- runtimeData.reader.on('app:about', () => {
+ runtimeData.plantform.reader.on('app:about', () => {
const popInfo = {
title:
app.config.globalProperties.$t('关于') +
@@ -408,41 +408,36 @@ export function createIpc() {
}
runtimeData.popBoxList.push(popInfo)
})
- runtimeData.reader.on('app:changeTab', (_, name) => {
+ runtimeData.plantform.reader.on('app:changeTab', (_, name) => {
document.getElementById('bar-' + name.toLowerCase())?.click()
})
- runtimeData.reader.on('app:openLink', (_, link) => {
+ runtimeData.plantform.reader.on('app:openLink', (_, link) => {
openLink(link)
})
- runtimeData.reader.on('app:error', (_, text) => {
+ runtimeData.plantform.reader.on('app:error', (_, text) => {
new Logger().add(LogType.ERR, text)
})
- runtimeData.reader.on('app:jumpChat', (_, info) => {
+ runtimeData.plantform.reader.on('app:jumpChat', (_, info) => {
jumpToChat(info.userId, info.msgId)
new Notify().closeAll(info.userId)
})
// 后端连接模式
- runtimeData.reader.on('onebot:onopen', (_, data) => {
+ runtimeData.plantform.reader.on('onebot:onopen', (_, data) => {
Connector.onopen(data.address, data.token)
})
- runtimeData.reader.on('onebot:onmessage', (_, message) => {
+ runtimeData.plantform.reader.on('onebot:onmessage', (_, message) => {
Connector.onmessage(message)
})
- runtimeData.reader.on('onebot:onclose', (_, data) => {
+ runtimeData.plantform.reader.on('onebot:onclose', (_, data) => {
Connector.onclose(data.code, data.reason, data.address, data.token)
})
}
}
-export function loadAppendStyle() {
+export async function loadAppendStyle() {
const platform = runtimeData.tags.platform
logger.info('正在装载补充样式……')
- if (runtimeData.tags.isElectron) {
- import('@renderer/assets/css/append/append_new.css').then(() => {
- logger.info('UI 2.0 附加样式加载完成')
- })
- }
if(platform != undefined) {
import(`@renderer/assets/css/append/append_${platform}.css`)
.then(() => {
@@ -451,7 +446,27 @@ export function loadAppendStyle() {
.catch(() => {
logger.info('未找到对应平台的附加样式')
})
+ if(platform == 'ios') {
+ const safeArea = await runtimeData.plantform.
+ pulgins.SafeArea?.getSafeArea()
+ if (safeArea) {
+ const app = document.getElementById('app')
+ if (app) {
+ app.style.paddingTop = safeArea.top + 'px'
+ app.style.height = 'calc(100% - ' + safeArea.top + 'px)'
+ }
+ }
+ runtimeData.sysConfig.fs_adaptation = safeArea.bottom - 10
+ }
+ }
+
+ // UI 2.0 附加样式
+ if (runtimeData.tags.isElectron) {
+ import('@renderer/assets/css/append/append_new.css').then(() => {
+ logger.info('UI 2.0 附加样式加载完成')
+ })
}
+ // 透明 UI 附加样式
let subVersion = runtimeData.tags.release?.split('.') as any
subVersion = subVersion ? Number(subVersion[2]) : 0
if (
@@ -463,7 +478,7 @@ export function loadAppendStyle() {
})
}
if (runtimeData.tags.isElectron && platform == 'linux') {
- const gnomeExtInfo = runtimeData.reader?.invoke('sys:getGnomeExt')
+ const gnomeExtInfo = runtimeData.plantform.reader?.invoke('sys:getGnomeExt')
if (gnomeExtInfo) {
gnomeExtInfo.then((info: any) => {
if (
@@ -742,8 +757,8 @@ export function BackendRequest(
cookies: string[],
data: any = undefined,
) {
- if (runtimeData.reader) {
- runtimeData.reader.send('sys:requestHttp', {
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('sys:requestHttp', {
type: type,
url: url,
cookies: JSON.stringify(cookies),
diff --git a/src/renderer/src/pages/Chat.vue b/src/renderer/src/pages/Chat.vue
index b5f782dc..e24b9f29 100644
--- a/src/renderer/src/pages/Chat.vue
+++ b/src/renderer/src/pages/Chat.vue
@@ -17,12 +17,9 @@
(runtimeData.tags.openSideBar ? ' open' : '') +
(runtimeData.sysConfig.opt_no_window ? ' withBar' : '')
"
- :style="
- `background-image: url(${runtimeData.sysConfig.chat_background});` +
- (Option.get('fs_adaptation') > 0
- ? '--append-fs-adaptation:' + Option.get('fs_adaptation') + 'px'
- : '--append-fs-adaptation:0px')
- ">
+ :style="`background-image: url(${runtimeData.sysConfig.chat_background});`"
+ @touchmove="ChatOnMove"
+ @touchend="chatMoveEnd">
0) {
+ (bg[1] as HTMLDivElement).style.height =
+ `calc(100% - ${safeArea.bottom}px - var(--append-fs-adaptation))`
+ }
+ if(mg && mg.length > 0) {
+ (mg[0] as HTMLDivElement).style.height =
+ `calc(100% - ${safeArea.bottom}px - var(--append-fs-adaptation))`
+ }
+ }
+ }
+ }
},
methods: {
/**
@@ -2513,31 +2540,18 @@
const dy = Math.abs(startY - event.targetTouches[0].pageY)
const x = startX - event.targetTouches[0].pageX
// 如果 dy 大于 10px 则判定为用户在滚动页面,打断长按消息判定
+ if (dy > 10) {
+ this.tags.chatTouch.onScroll = true
+ }
if (dy > 10 || dx > 5) {
if (this.tags.msgTouch.msgOnTouchDown) {
- logger.add(
- LogType.UI,
- '用户正在滑动,打断长按判定。',
- )
+ logger.add(LogType.UI, '用户正在滑动,打断长按判定。')
this.tags.msgTouch.msgOnTouchDown = false
}
}
if (dy < sender.offsetHeight / 3 && dy < 40) {
this.tags.msgTouch.onMove = 'on'
- if (x < -10) {
- // 左滑
- if (dx >= sender.offsetWidth / 3) {
- this.tags.msgTouch.onMove = 'right'
- logger.add(
- LogType.UI,
- '触发右滑判定 ……(转发)',
- )
- } else {
- sender.style.transform =
- 'translate(' + (Math.sqrt(dx) + 5) + 'px)'
- sender.style.transition = 'transform 0s'
- }
- } else if (x > 10) {
+ if (x > 10) {
// 右滑
if (dx >= sender.offsetWidth / 3) {
this.tags.msgTouch.onMove = 'left'
@@ -2697,6 +2711,55 @@
openLeftBar() {
runtimeData.tags.openSideBar = !runtimeData.tags.openSideBar
},
+
+ // 聊天面板右滑操作
+ ChatOnMove(event: TouchEvent) {
+ const chatPan = document.getElementById('chat-pan')
+ if(chatPan) {
+ // 暂时去除 transition 过渡防止不跟手
+ chatPan.style.transition = 'all 0s'
+ // 获取 x 轴的位置
+ const x = event.targetTouches[0].pageX
+ const y = event.targetTouches[0].pageY
+ // 记录开始位置
+ if(this.tags.chatTouch.startX == -1) {
+ this.tags.chatTouch.startX = x
+ }
+ if(this.tags.chatTouch.startY == -1) {
+ this.tags.chatTouch.startY = y
+ }
+ const moveX = Math.abs(x - this.tags.chatTouch.startX)
+ const moveY = Math.abs(y - this.tags.chatTouch.startY)
+ const width = document.body.clientWidth
+ if((moveX > moveY || moveX > 20)
+ && x - this.tags.chatTouch.startX > 0) {
+ chatPan.style.transform =
+ 'translateX(' + (x - this.tags.chatTouch.startX) + 'px)'
+ this.tags.chatTouch.openSuccess = moveX > width / 3
+ }
+ }
+ },
+
+ // 聊天面板右滑结束
+ chatMoveEnd() {
+ this.tags.chatTouch.startX = -1
+ const chatPan = document.getElementById('chat-pan')
+ if(chatPan) {
+ if(!this.tags.chatTouch.openSuccess) {
+ runtimeData.tags.openSideBar = false
+ } else {
+ runtimeData.tags.openSideBar = true
+ new Logger().add(LogType.UI, '右滑打开侧边栏触发完成')
+ }
+ // 恢复过渡效果,完成撒手之后的剩余动画
+ chatPan.style.transition = ''
+ setTimeout(() => {
+ chatPan.style.transform = ''
+ }, 100)
+ }
+ this.tags.chatTouch.openSuccess = false
+ this.tags.chatTouch.onScroll = false
+ }
},
})
diff --git a/src/renderer/src/pages/Friends.vue b/src/renderer/src/pages/Friends.vue
index 7a517250..93bbd539 100644
--- a/src/renderer/src/pages/Friends.vue
+++ b/src/renderer/src/pages/Friends.vue
@@ -398,4 +398,9 @@
display: none;
}
}
+ @media (max-width: 500px) {
+ .exp-header > span {
+ display: block !important;
+ }
+ }
diff --git a/src/renderer/src/pages/Messages.vue b/src/renderer/src/pages/Messages.vue
index da233243..7a4e8719 100644
--- a/src/renderer/src/pages/Messages.vue
+++ b/src/renderer/src/pages/Messages.vue
@@ -25,7 +25,7 @@
@click="cleanList" />
-
{{
+ {{
$t('消息')
}}
@@ -175,7 +175,7 @@
},
mounted() {
library.add(faCheckToSlot, faThumbTack, faTrashCan, faGripLines)
- if (runtimeData.tags.isElectron && runtimeData.reader) {
+ if (runtimeData.tags.isElectron && runtimeData.plantform.reader) {
this.$watch(
() => runtimeData.onMsgList.length,
() => {
@@ -209,7 +209,7 @@
'/0',
})
})
- runtimeData.reader?.send('sys:flushTouchBar', list)
+ runtimeData.plantform.reader?.send('sys:flushTouchBar', list)
},
)
}
diff --git a/src/renderer/src/pages/options/OptDev.vue b/src/renderer/src/pages/options/OptDev.vue
index 4470194d..bc44d7fa 100644
--- a/src/renderer/src/pages/options/OptDev.vue
+++ b/src/renderer/src/pages/options/OptDev.vue
@@ -317,8 +317,8 @@
console.log(runtimeData)
console.log('=========================')
/* eslint-enable no-console */
- if (runtimeData.reader) {
- runtimeData.reader.send('win:openDevTools')
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('win:openDevTools')
}
},
async printVersionInfo() {
@@ -329,9 +329,9 @@
// electron:索要 electron 信息
let addInfo = undefined
- if (runtimeData.reader) {
+ if (runtimeData.plantform.reader) {
addInfo =
- await runtimeData.reader.invoke('opt:getSystemInfo')
+ await runtimeData.plantform.reader.invoke('opt:getSystemInfo')
}
const browser = detect() as BrowserInfo
@@ -353,7 +353,7 @@
// 获取安装信息,这儿主要判断几种已提交的包管理安装方式
if (
runtimeData.tags.isElectron &&
- runtimeData.reader &&
+ runtimeData.plantform.reader &&
runtimeData.tags.release
) {
const process = window.electron?.process
@@ -366,7 +366,7 @@
.indexOf('arch') > 0
) {
let pacmanInfo =
- await runtimeData.reader.invoke(
+ await runtimeData.plantform.reader.invoke(
'sys:runCommand',
'pacman -Q stapxs-qq-lite-bin',
)
@@ -375,7 +375,7 @@
} else {
// 也有可能是 stapxs-qq-lite,这是我自己打的原生包
pacmanInfo =
- await runtimeData.reader.invoke(
+ await runtimeData.plantform.reader.invoke(
'sys:runCommand',
'pacman -Q stapxs-qq-lite',
)
@@ -543,8 +543,8 @@
';path=/',
)
})
- if (runtimeData.reader) {
- runtimeData.reader.sendSync('opt:clearAll')
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.sendSync('opt:clearAll')
}
location.reload()
},
@@ -561,8 +561,8 @@
runtimeData.popBoxList.push(popInfo)
},
restartapp() {
- if (runtimeData.reader) {
- runtimeData.reader.send('win:relaunch')
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('win:relaunch')
}
},
getBotTypeName(index: BotMsgType) {
diff --git a/src/renderer/src/pages/options/OptView.vue b/src/renderer/src/pages/options/OptView.vue
index 17b08716..0b277883 100644
--- a/src/renderer/src/pages/options/OptView.vue
+++ b/src/renderer/src/pages/options/OptView.vue
@@ -399,8 +399,8 @@
},
restartapp() {
- if (runtimeData.reader) {
- runtimeData.reader.send('win:relaunch')
+ if (runtimeData.plantform.reader) {
+ runtimeData.plantform.reader.send('win:relaunch')
}
},
diff --git a/ssqq.web-quick-start/.gitignore b/ssqq.npx-web-quick-start/.gitignore
similarity index 100%
rename from ssqq.web-quick-start/.gitignore
rename to ssqq.npx-web-quick-start/.gitignore
diff --git a/ssqq.web-quick-start/.npmignore b/ssqq.npx-web-quick-start/.npmignore
similarity index 100%
rename from ssqq.web-quick-start/.npmignore
rename to ssqq.npx-web-quick-start/.npmignore
diff --git a/ssqq.web-quick-start/index.ts b/ssqq.npx-web-quick-start/index.ts
similarity index 100%
rename from ssqq.web-quick-start/index.ts
rename to ssqq.npx-web-quick-start/index.ts
diff --git a/ssqq.web-quick-start/package.json b/ssqq.npx-web-quick-start/package.json
similarity index 100%
rename from ssqq.web-quick-start/package.json
rename to ssqq.npx-web-quick-start/package.json
diff --git a/ssqq.web-quick-start/tsconfig.json b/ssqq.npx-web-quick-start/tsconfig.json
similarity index 100%
rename from ssqq.web-quick-start/tsconfig.json
rename to ssqq.npx-web-quick-start/tsconfig.json
diff --git a/ssqq.web-quick-start/update.ts b/ssqq.npx-web-quick-start/update.ts
similarity index 100%
rename from ssqq.web-quick-start/update.ts
rename to ssqq.npx-web-quick-start/update.ts