auto sync, dep updates, other stuff
This commit is contained in:
parent
0577a0311a
commit
c76ff2ac36
12
debug.log
Normal file
12
debug.log
Normal file
@ -0,0 +1,12 @@
|
||||
[0813/143821.763:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143822.005:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143823.091:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143823.102:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143823.114:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143823.926:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143914.910:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143915.186:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143917.426:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143917.460:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143917.472:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143917.910:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
155
package-lock.json
generated
155
package-lock.json
generated
@ -1,27 +1,29 @@
|
||||
{
|
||||
"name": "fanslysync-desktop",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "fanslysync-desktop",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.3",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-autostart": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-notification": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-updater": "^2.0.0-rc.0"
|
||||
"@tauri-apps/plugin-updater": "^2.0.0-rc.0",
|
||||
"svelte-french-toast": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-static": "^3.0.2",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@tauri-apps/cli": "^2.0.0-rc.0",
|
||||
"@tauri-apps/cli": "^2.0.0-rc.3",
|
||||
"@types/eslint": "^8.56.7",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^9.0.0",
|
||||
@ -56,7 +58,6 @@
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://npm.hep.gg/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
@ -610,7 +611,6 @@
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://npm.hep.gg/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
@ -624,7 +624,6 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://npm.hep.gg/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -633,7 +632,6 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://npm.hep.gg/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -641,14 +639,12 @@
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://npm.hep.gg/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://npm.hep.gg/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
@ -1020,9 +1016,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli/-/cli-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-X9N/R7e3zeTpU0HgQi2kaNYncMFoSTzXstnUyGOcKrJcCkR4ebbA2nYqhGvIPfglLKHNFRTZwfPNhixx2Ftxxg==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli/-/cli-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-iNF95pieBmverl1EmQyqh+fhcIClS544fN5Ex5lAbYLTiHZ/gm3lOfVBhF6NPaKd/sfLuy7K1tfDXlHztBfANw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tauri": "tauri.js"
|
||||
@ -1035,22 +1031,22 @@
|
||||
"url": "https://opencollective.com/tauri"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.0",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.0"
|
||||
"@tauri-apps/cli-darwin-arm64": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-darwin-x64": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-linux-arm-gnueabihf": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-linux-arm64-gnu": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-linux-arm64-musl": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-linux-x64-gnu": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-linux-x64-musl": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-win32-arm64-msvc": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-win32-ia32-msvc": "2.0.0-rc.3",
|
||||
"@tauri-apps/cli-win32-x64-msvc": "2.0.0-rc.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-arm64": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-jpQc++6ESFUuBpoXvJNPTRtrmToMIByOynZ4K5SAwI9RkKUikSaDmlRZV0GisOVPT7TT08khk7MPtAQeFyjqwA==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-szYCSr/ChbCF+S6Wnr15TYpI2cZR07d+AQOiFGuScP0preM8Pbsk/sb0hfLwqzepjVFFNVWQba9sG7FEW2Y2XA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1064,9 +1060,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-darwin-x64": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-EnqsgcNUwH29YjQ4JdBID5kILQQdIJgZ36VQgtju/BBvnd1lr+6Bswdk1/4y41hhAVz9WyHeMCnTH33CSKvNxw==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-BJv6EJOY1DJbRzVtfg8CcBAlnS5OjhBAc5YKjh4BT7EyOcop8HStBSxhL6yjWrUP7eLR1iIsW/uSehVJwzYIdQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1080,9 +1076,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm-gnueabihf": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-YKg/qThAmQYRToiV8lx/DvMf0VaUJAutIfv8ALq9Or4zdg7mZlAlKvF+7lZQQRmKhQ62+0gnoJS2HyN8feaagw==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-fwx805/xL4sF/EdMYqcUHQHzMYwo+OVTBTz5x/JWK8D57rnmLHAP+ZhnfFsZQLRo2QRT2l1Ye3bDyU+QRA1JFA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -1096,9 +1092,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-gnu": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-UnflWuNhH/u41GSmG1jm6qhWUM4o1AB463QCaf2fAjLo5GWiI78U6rJOOXZvOOmWIQuzsmAUZjNDORWW13+osA==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-3KauzO1Ls4kuY0nr82S4X8XFxlQAMN+Mqp8LLqvQ+PPMp92XQAkPH7osQdoHIEoW5gsE69U2JaiQ5tHSqNM9og==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1112,9 +1108,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-arm64-musl": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-sWRaDyb332gtHWHr0KvoLzkzvXqRpZ0vpQYxKF2/mIZtaUuMtU56GmRwFVX4VjQYgWb3yWmzTr+tEKjCjXbjng==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-ngHS0foffm1xO5gqnDKGeYMKj8ceGmrFP5dDldoaaMQubw1SyFa0pRUjb7fZSYiO7F4SOSa8NYeMqlF9peZmnQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1128,9 +1124,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-gnu": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-1dokW+9ZfhwzwYz42jYR5A0/VnGoEGVW7HyN1N6KvHeL1FpSbh0LoTsDODjVjZSjXd62+Aac/stbJqBZChQWbA==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-0/am9pVvuUHGmz32M8ffz1fpLnc08j3nzcRe5wUdL2AxfT+wKMII+Dn99GtCVgcdDW4jSXDMRUwrBkGocGC2OA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1144,9 +1140,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-linux-x64-musl": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-7tb34p3vLEGS4pGRpmxcz7eq37yD7DVe4XFfgj8ZO0KsaRBVivzNK2snNDLnd0dVZcx/lJjZc8Cf0B5W1/x/Jw==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-r7mRi8q8TqTFVjb9kAsU7IgwUgno2s8Ip4xwq9psQhlRE3JGEZQmSEcy1jqTjfl6KFh6lJcDR7l+9/EMhL/D3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1160,9 +1156,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-arm64-msvc": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-Ilw3Gro8ZBew9yfBXcaET9lLj0g4jehWDMH6j2Wdje1rnvBbQShMaSn3WNMfJypyet5nqM88nGA3YipzmVcIBA==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-2J6KjmDIQCw6HF1X6/yPcd+JLl7pxrH2zVMGmNllaoWhHeByvRobqFWnT7gcdHaA3dGTo432CwWvOgTgrINQpQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1176,9 +1172,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-ia32-msvc": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-AWzgDlvv0BssWH3aNsDXLRkKbGynWdm5X6DenSQKtZm5dmDBZsNlZRMgkyPb8WSHK/7ARznKs2OdnkuHWuh9ww==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-8q75CsHDSEDdgi6xPwim+BaQZFCswK2Dn/qL38V3Mh9kmVvC8oGJMPC66bC20dF+v3KWeFm2FNNGQqOSXCveHg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -1192,9 +1188,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/cli-win32-x64-msvc": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-zmXDUkBmzZ6lk6jT6AoOAE2w+kmkLX5uf/vaJHHzE6WsrZ6UymH0HTLwbRXhaplvpnzXGVyLuSlv3/BK6Q69aQ==",
|
||||
"version": "2.0.0-rc.3",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-2.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-qeBRJYalahxEXolekcpZJ/HBrIJacG2NWJBGhhi797mIwnbmlpbHMc8blIJtNNNwVUb2BjXuxKQVfojQ5YYrcg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1207,6 +1203,14 @@
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-autostart": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/plugin-autostart/-/plugin-autostart-2.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-V49lm++vhrMPPDGMtmOcbJLF4TYu78ZmAiMhyd4FFnbYlgin6ZTjiMCFEl4JKVy2lqP3C8DQvXf/gkUMuER7Iw==",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0-rc.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tauri-apps/plugin-clipboard-manager": {
|
||||
"version": "2.0.0-rc.0",
|
||||
"resolved": "https://npm.hep.gg/@tauri-apps/plugin-clipboard-manager/-/plugin-clipboard-manager-2.0.0-rc.0.tgz",
|
||||
@ -1274,8 +1278,7 @@
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://npm.hep.gg/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
@ -1511,7 +1514,6 @@
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://npm.hep.gg/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -1603,7 +1605,6 @@
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://npm.hep.gg/aria-query/-/aria-query-5.3.0.tgz",
|
||||
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.3"
|
||||
}
|
||||
@ -1658,7 +1659,6 @@
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://npm.hep.gg/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@ -1838,7 +1838,6 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://npm.hep.gg/code-red/-/code-red-1.0.4.tgz",
|
||||
"integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||
"@types/estree": "^1.0.1",
|
||||
@ -1907,7 +1906,6 @@
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://npm.hep.gg/css-tree/-/css-tree-2.3.1.tgz",
|
||||
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mdn-data": "2.0.30",
|
||||
"source-map-js": "^1.0.1"
|
||||
@ -1964,7 +1962,6 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://npm.hep.gg/dequal/-/dequal-2.0.3.tgz",
|
||||
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@ -2291,7 +2288,6 @@
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://npm.hep.gg/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0"
|
||||
}
|
||||
@ -2725,7 +2721,6 @@
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://npm.hep.gg/is-reference/-/is-reference-3.0.2.tgz",
|
||||
"integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
@ -2845,8 +2840,7 @@
|
||||
"node_modules/locate-character": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://npm.hep.gg/locate-character/-/locate-character-3.0.0.tgz",
|
||||
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
@ -2879,7 +2873,6 @@
|
||||
"version": "0.30.10",
|
||||
"resolved": "https://npm.hep.gg/magic-string/-/magic-string-0.30.10.tgz",
|
||||
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
}
|
||||
@ -2887,8 +2880,7 @@
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.0.30",
|
||||
"resolved": "https://npm.hep.gg/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
@ -3200,7 +3192,6 @@
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://npm.hep.gg/periscopic/-/periscopic-3.1.0.tgz",
|
||||
"integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^3.0.0",
|
||||
@ -3729,7 +3720,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://npm.hep.gg/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -3942,7 +3932,6 @@
|
||||
"version": "4.2.18",
|
||||
"resolved": "https://npm.hep.gg/svelte/-/svelte-4.2.18.tgz",
|
||||
"integrity": "sha512-d0FdzYIiAePqRJEb90WlJDkjUEx42xhivxN8muUBmfZnP+tzUgz12DJ2hRJi8sIHCME7jeK1PTMgKPSfTd8JrA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||
@ -4055,6 +4044,17 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-french-toast": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://npm.hep.gg/svelte-french-toast/-/svelte-french-toast-1.2.0.tgz",
|
||||
"integrity": "sha512-5PW+6RFX3xQPbR44CngYAP1Sd9oCq9P2FOox4FZffzJuZI2mHOB7q5gJBVnOiLF5y3moVGZ7u2bYt7+yPAgcEQ==",
|
||||
"dependencies": {
|
||||
"svelte-writable-derived": "^3.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.57.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-hmr": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://npm.hep.gg/svelte-hmr/-/svelte-hmr-0.16.0.tgz",
|
||||
@ -4129,6 +4129,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-writable-derived": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://npm.hep.gg/svelte-writable-derived/-/svelte-writable-derived-3.1.1.tgz",
|
||||
"integrity": "sha512-w4LR6/bYZEuCs7SGr+M54oipk/UQKtiMadyOhW0PTwAtJ/Ai12QS77sLngEcfBx2q4H8ZBQucc9ktSA5sUGZWw==",
|
||||
"funding": {
|
||||
"url": "https://ko-fi.com/pixievoltno1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.2.1 || ^4.0.0-next.1 || ^5.0.0-next.94"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.4.6",
|
||||
"resolved": "https://npm.hep.gg/tailwindcss/-/tailwindcss-3.4.6.tgz",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fanslysync-desktop",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@ -17,7 +17,7 @@
|
||||
"@sveltejs/adapter-static": "^3.0.2",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@tauri-apps/cli": "^2.0.0-rc.0",
|
||||
"@tauri-apps/cli": "^2.0.0-rc.3",
|
||||
"@types/eslint": "^8.56.7",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^9.0.0",
|
||||
@ -38,11 +38,13 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-autostart": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-log": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-notification": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-os": "^2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-updater": "^2.0.0-rc.0"
|
||||
"@tauri-apps/plugin-updater": "^2.0.0-rc.0",
|
||||
"svelte-french-toast": "^1.2.0"
|
||||
}
|
||||
}
|
||||
|
391
src-tauri/Cargo.lock
generated
391
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "app"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
description = "A Tauri App"
|
||||
authors = ["SticksDev"]
|
||||
license = "MIT"
|
||||
@ -12,26 +12,29 @@ rust-version = "1.80"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.0-rc", features = [] }
|
||||
tauri-build = { version = "2.0.0-rc.2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "2.0.0-rc", features = [] }
|
||||
tauri = { version = "2.0.0-rc.2", features = [] }
|
||||
dirs = "5.0.1"
|
||||
reqwest = { version = "0.11.18", features = ["json"] }
|
||||
lazy_static = "1.5.0"
|
||||
tokio = { version = "1.29.1", features = ["full"] }
|
||||
tokio-macros = "2.3.0"
|
||||
tauri-plugin-os = "2.0.0-alpha.2"
|
||||
tauri-plugin-dialog = "2.0.0-alpha.2"
|
||||
tauri-plugin-clipboard-manager = "2.0.0-alpha.2"
|
||||
tauri-plugin-notification = "2.0.0-alpha.3"
|
||||
tauri-plugin-updater = "2.0.0-alpha.3"
|
||||
tauri-plugin-log = "2.0.0-rc.0"
|
||||
tauri-plugin-os = { version = "2.0.0-rc" }
|
||||
tauri-plugin-dialog = { version = "2.0.0-rc" }
|
||||
tauri-plugin-clipboard-manager = { version = "2.0.0-rc" }
|
||||
tauri-plugin-notification = { version = "2.0.0-rc" }
|
||||
tauri-plugin-updater = { version = "2.0.0-rc" }
|
||||
tauri-plugin-log = { version = "2.0.0-rc" }
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
||||
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
|
||||
# DO NOT REMOVE!!
|
||||
custom-protocol = [ "tauri/custom-protocol" ]
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-autostart = "2.0.0-rc.0"
|
||||
|
@ -2,9 +2,7 @@
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"dialog:allow-message",
|
||||
@ -28,6 +26,7 @@
|
||||
"clipboard-manager:default",
|
||||
"notification:default",
|
||||
"updater:default",
|
||||
"log:default"
|
||||
"log:default",
|
||||
"autostart:default"
|
||||
]
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","notification:default","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","os:default","dialog:default","clipboard-manager:default","notification:default","updater:default","log:default"]}}
|
||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","notification:default","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","os:default","dialog:default","clipboard-manager:default","notification:default","updater:default","log:default","autostart:default"]}}
|
@ -171,6 +171,55 @@
|
||||
},
|
||||
"Identifier": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "autostart:default -> This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
||||
"type": "string",
|
||||
|
@ -171,6 +171,55 @@
|
||||
},
|
||||
"Identifier": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "autostart:default -> This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:default"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:allow-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-disable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-enable"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"autostart:deny-is-enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "clipboard-manager:default -> No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
|
||||
"type": "string",
|
||||
|
@ -3,6 +3,7 @@ use crate::{
|
||||
structs::{FanslyAccountResponse, FanslyBaseResponse, SyncDataResponse},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use serde_json::Value;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
@ -26,9 +27,34 @@ pub async fn fansly_get_me() -> Result<FanslyBaseResponse<FanslyAccountResponse>
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fansly_sync() -> Result<SyncDataResponse, String> {
|
||||
pub async fn fansly_sync(auto: bool) -> Result<SyncDataResponse, String> {
|
||||
let fansly = FANSLY.lock().await;
|
||||
let response = fansly.sync().await;
|
||||
let response = fansly.sync(auto).await;
|
||||
|
||||
match response {
|
||||
Ok(response) => Ok(response),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fansly_upload_auto_sync_data(
|
||||
data: SyncDataResponse,
|
||||
token: String,
|
||||
) -> Result<(), String> {
|
||||
let fansly: tokio::sync::MutexGuard<Fansly> = FANSLY.lock().await;
|
||||
let response = fansly.upload_auto_sync_data(data, token).await;
|
||||
|
||||
match response {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fansly_check_sync_token(token: String) -> Result<Value, String> {
|
||||
let fansly: tokio::sync::MutexGuard<Fansly> = FANSLY.lock().await;
|
||||
let response = fansly.check_sync_token(token).await;
|
||||
|
||||
match response {
|
||||
Ok(response) => Ok(response),
|
||||
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::structs::{FanslyFollowersResponse, Subscription};
|
||||
|
||||
const CURRENT_VERSION: i32 = 1; // Set the current version of the config
|
||||
const CURRENT_VERSION: i32 = 2; // Set the current version of the config
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SyncData {
|
||||
@ -18,6 +18,8 @@ pub struct Config {
|
||||
pub version: i32, // Add a version field to the config (1, 2, 3, etc.)
|
||||
pub is_first_run: bool,
|
||||
pub fansly_token: String,
|
||||
pub auto_sync_enabled: bool,
|
||||
pub sync_token: String,
|
||||
pub sync_interval: u64,
|
||||
pub last_sync: u64,
|
||||
pub last_sync_data: SyncData,
|
||||
@ -31,6 +33,8 @@ impl Default for Config {
|
||||
fansly_token: String::new(), // Fansly token is stored as a string
|
||||
sync_interval: 1, // Every hour - sync interval is interpreted as hours
|
||||
last_sync: 0, // Last sync time is stored as a UNIX timestamp
|
||||
auto_sync_enabled: false, // Auto sync is disabled by default
|
||||
sync_token: String::new(), // Sync token is stored as a string
|
||||
last_sync_data: SyncData {
|
||||
followers: Vec::new(),
|
||||
subscribers: Vec::new(),
|
||||
@ -42,17 +46,89 @@ impl Default for Config {
|
||||
impl Config {
|
||||
pub fn load_or_create(path: &Path) -> io::Result<Self> {
|
||||
if path.exists() {
|
||||
let mut config: Self = serde_json::from_str(std::fs::read_to_string(path)?.as_str())
|
||||
.map_err(|e| {
|
||||
io::Error::new(
|
||||
let config_result: Result<Self, _> =
|
||||
serde_json::from_str(&std::fs::read_to_string(path)?);
|
||||
let config = match config_result {
|
||||
Ok(config) => config,
|
||||
Err(_) => {
|
||||
// Load raw JSON and attempt to parse it as a JSON object
|
||||
let config_raw = std::fs::read_to_string(path)?;
|
||||
let config_json: serde_json::Value = serde_json::from_str(&config_raw)?;
|
||||
|
||||
println!("[config::migrate] Migrating config file to latest version...");
|
||||
println!(
|
||||
"[config::migrate] [DEBUG] config is_object: {}",
|
||||
config_json.is_object()
|
||||
);
|
||||
|
||||
// Check if the JSON object is valid, if not, return an error
|
||||
if !config_json.is_object() {
|
||||
println!(
|
||||
"[config::migrate] [ERROR] Found invalid JSON object in config file"
|
||||
);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!("Could not parse config file: {}", e),
|
||||
)
|
||||
})?;
|
||||
if config.version != CURRENT_VERSION {
|
||||
"Tried to migrate a config file, but found an invalid JSON object",
|
||||
));
|
||||
}
|
||||
|
||||
// Get the version field from the JSON object
|
||||
let version = config_json["version"].as_i64().unwrap_or(0) as i32;
|
||||
|
||||
// Check if the version field is a valid integer, if not, return an error
|
||||
if version == 0 {
|
||||
println!(
|
||||
"[config::migrate] [ERROR] Found invalid version field in config JSON"
|
||||
);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Tried to migrate a config file, but found an invalid version field",
|
||||
));
|
||||
}
|
||||
|
||||
println!(
|
||||
"[config::migrate] Found version field in config JSON: {}",
|
||||
version
|
||||
);
|
||||
|
||||
// Now create a new Config object and set the version field to the value we found
|
||||
let mut config = Config::default();
|
||||
config.version = version;
|
||||
|
||||
// Retain important fields from the JSON object
|
||||
config.is_first_run = config_json["is_first_run"].as_bool().unwrap_or(true);
|
||||
config.fansly_token = config_json["fansly_token"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
config.sync_token =
|
||||
config_json["sync_token"].as_str().unwrap_or("").to_string();
|
||||
config.sync_interval =
|
||||
config_json["sync_interval"].as_i64().unwrap_or(1) as u64;
|
||||
|
||||
// Run migrations on the config object and save it
|
||||
config = config.migrate()?;
|
||||
config.save(path)?;
|
||||
|
||||
println!(
|
||||
"[config::migrate] Successfully migrated config file to latest version"
|
||||
);
|
||||
// Recursively call load_or_create to load the migrated config
|
||||
return Config::load_or_create(path);
|
||||
}
|
||||
};
|
||||
|
||||
if config.version != CURRENT_VERSION {
|
||||
// Should have been migrated by now, error out because it wasn't
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"Config version mismatch: expected {}, got {}. Please try removing the config file and restarting the application.",
|
||||
CURRENT_VERSION, config.version
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
} else {
|
||||
let saved_config = Config::default().save(path);
|
||||
@ -66,8 +142,12 @@ impl Config {
|
||||
while self.version < CURRENT_VERSION {
|
||||
self = match self.version {
|
||||
1 => {
|
||||
// If we're on version 1, migrate to version 2 (not implemented)
|
||||
self.version += 1;
|
||||
// Migrate from version 1 to version 2
|
||||
self.version = 2;
|
||||
self.auto_sync_enabled = false;
|
||||
self.sync_token = String::new();
|
||||
self.sync_interval = 1;
|
||||
|
||||
self
|
||||
}
|
||||
_ => {
|
||||
|
@ -5,6 +5,7 @@ use crate::structs::{
|
||||
FanslySubscriptionsResponse, Subscription, SyncDataResponse,
|
||||
};
|
||||
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
|
||||
use serde_json::Value;
|
||||
|
||||
pub struct Fansly {
|
||||
client: reqwest::Client,
|
||||
@ -195,7 +196,73 @@ impl Fansly {
|
||||
Ok(format!("https://paste.hep.gg/{}", key))
|
||||
}
|
||||
|
||||
pub async fn sync(&self) -> Result<SyncDataResponse, String> {
|
||||
pub async fn upload_auto_sync_data(
|
||||
&self,
|
||||
data: SyncDataResponse,
|
||||
token: String,
|
||||
) -> Result<(), reqwest::Error> {
|
||||
let url = "http://localhost:5001/sync";
|
||||
|
||||
// Set our content type to application/json
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
headers.insert(
|
||||
reqwest::header::CONTENT_TYPE,
|
||||
"application/json".parse().unwrap(),
|
||||
);
|
||||
|
||||
// Add our auth token to the headers
|
||||
headers.insert("Authorization", format!("{}", token).parse().unwrap());
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.post(url)
|
||||
.headers(headers)
|
||||
.json(&data)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
eprintln!("[sync::process::upload_auto_sync_data] Failed to upload sync data.");
|
||||
return Err(response.error_for_status().unwrap_err());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn check_sync_token(&self, token: String) -> Result<Value, reqwest::Error> {
|
||||
// Check if the token is valid (GET /checkSyncToken with Authorization header)
|
||||
// If it is, return the data back from the API
|
||||
// If it isn't, return an error
|
||||
let url = "http://localhost:5001/checkSyncToken";
|
||||
|
||||
// Set our content type to application/json
|
||||
let mut headers = reqwest::header::HeaderMap::new();
|
||||
headers.insert(
|
||||
reqwest::header::CONTENT_TYPE,
|
||||
"application/json".parse().unwrap(),
|
||||
);
|
||||
|
||||
// Add our auth token to the headers
|
||||
headers.insert("Authorization", format!("{}", token).parse().unwrap());
|
||||
|
||||
let response = self.client.get(url).headers(headers).send().await;
|
||||
|
||||
// If successful, return the data, otherwise return an error
|
||||
match response {
|
||||
Ok(response) => {
|
||||
if !response.status().is_success() {
|
||||
eprintln!("[sync::process::check_sync_token] Failed to check sync token.");
|
||||
return Err(response.error_for_status().unwrap_err());
|
||||
}
|
||||
|
||||
let json: serde_json::Value = response.json().await?;
|
||||
Ok(json)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn sync(&self, auto: bool) -> Result<SyncDataResponse, String> {
|
||||
// Fetch profile
|
||||
println!("[sync::process] Fetching profile...");
|
||||
let profile = self.get_profile().await.map_err(|e| e.to_string())?;
|
||||
@ -280,6 +347,7 @@ impl Fansly {
|
||||
println!("[sync::process] Uploading sync data to paste.hep.gg for processing...");
|
||||
|
||||
// Upload sync data to paste.hep.gg
|
||||
if !auto {
|
||||
let paste_url = self
|
||||
.upload_sync_data(SyncDataResponse {
|
||||
followers: followers.clone(),
|
||||
@ -295,5 +363,13 @@ impl Fansly {
|
||||
subscribers,
|
||||
sync_data_url: paste_url,
|
||||
})
|
||||
} else {
|
||||
// Return JSON of what we fetched
|
||||
Ok(SyncDataResponse {
|
||||
followers,
|
||||
subscribers,
|
||||
sync_data_url: "".to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,12 @@ use std::fs;
|
||||
use std::io;
|
||||
|
||||
use commands::config::{get_config, init_config, save_config};
|
||||
use commands::fansly::{fansly_get_me, fansly_set_token, fansly_sync};
|
||||
use commands::fansly::{
|
||||
fansly_check_sync_token, fansly_get_me, fansly_set_token, fansly_sync,
|
||||
fansly_upload_auto_sync_data,
|
||||
};
|
||||
use commands::utils::quit;
|
||||
use tauri_plugin_autostart::MacosLauncher;
|
||||
use tauri_plugin_log::{Target, TargetKind};
|
||||
|
||||
fn get_log_path() -> io::Result<String> {
|
||||
@ -31,6 +35,10 @@ fn get_log_path() -> io::Result<String> {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_autostart::init(
|
||||
MacosLauncher::LaunchAgent,
|
||||
None,
|
||||
))
|
||||
.plugin(tauri_plugin_log::Builder::new().build())
|
||||
.plugin(tauri_plugin_notification::init())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
@ -55,7 +63,9 @@ async fn main() {
|
||||
quit,
|
||||
fansly_set_token,
|
||||
fansly_get_me,
|
||||
fansly_sync
|
||||
fansly_sync,
|
||||
fansly_upload_auto_sync_data,
|
||||
fansly_check_sync_token
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
@ -2,6 +2,8 @@ export type Config = {
|
||||
version: number;
|
||||
is_first_run: boolean;
|
||||
fansly_token: string;
|
||||
auto_sync_enabled: boolean;
|
||||
sync_token: string;
|
||||
sync_interval: number;
|
||||
last_sync: number;
|
||||
last_sync_data: SyncData;
|
||||
|
@ -1,5 +1,7 @@
|
||||
<script>
|
||||
import '../app.css';
|
||||
import { Toaster } from 'svelte-french-toast';
|
||||
</script>
|
||||
|
||||
<Toaster position='bottom-center' />
|
||||
<slot />
|
||||
|
@ -87,8 +87,20 @@
|
||||
info(`[FanslySync::init] Not first run. Setting Fansly token...`);
|
||||
await invoke('fansly_set_token', { token: config.fansly_token });
|
||||
info(`[FanslySync::init] Fansly token set.`);
|
||||
info(`[FanslySync::init] Initialization complete. Redirecting to /home...`);
|
||||
window.location.href = '/home';
|
||||
info(`[FanslySync::init] Checking token validity...`);
|
||||
|
||||
const [valid, validError] = await awaiter(invoke('fansly_get_me'));
|
||||
if (validError) {
|
||||
error(`[FanslySync::init] Token invalid. Redirecting to /setup...`);
|
||||
await message(
|
||||
`Your Fansly token is invalid. Please re-enter your token in the setup page.`,
|
||||
{ title: 'FanslySync | Token Invalid', kind: 'error' }
|
||||
);
|
||||
window.location.href = '/setup';
|
||||
} else {
|
||||
info(`[FanslySync::init] Token valid. Redirecting to /dashboard...`);
|
||||
window.location.href = '/dashboard';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -3,7 +3,7 @@
|
||||
import { awaiter } from '$lib/utils';
|
||||
import { onMount } from 'svelte';
|
||||
import type { Config, SyncData } from '$lib/types';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { fade, fly, slide } from 'svelte/transition';
|
||||
import { sendNotification } from '@tauri-apps/plugin-notification';
|
||||
import { platform } from '@tauri-apps/plugin-os';
|
||||
import { check, Update } from '@tauri-apps/plugin-updater';
|
||||
@ -11,6 +11,8 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { ask, message } from '@tauri-apps/plugin-dialog';
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
import { isEnabled, enable } from '@tauri-apps/plugin-autostart';
|
||||
import { toast } from 'svelte-french-toast';
|
||||
|
||||
let loadingSync = true;
|
||||
let upToDate: boolean | null = null;
|
||||
@ -28,7 +30,20 @@
|
||||
message: ''
|
||||
};
|
||||
|
||||
let isAutoSyncConfigModalOpen = false;
|
||||
let canSave = false;
|
||||
let config: Config | null = null;
|
||||
let syncInterval: number | null = null;
|
||||
|
||||
let autoSyncConfig = {
|
||||
interval: 0,
|
||||
syncToken: ''
|
||||
};
|
||||
|
||||
let autoSyncConfigState = {
|
||||
validatingToken: false,
|
||||
tokenValid: false
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
info(`[FanslySync::page_init:home] onMount() called. Starting page initialization...`);
|
||||
@ -55,6 +70,8 @@
|
||||
`[FanslySync::page_init:home] Configuration initialized successfully. Checking for updates...`
|
||||
);
|
||||
config = configData;
|
||||
autoSyncConfig.interval = config.sync_interval;
|
||||
autoSyncConfig.syncToken = config.sync_token;
|
||||
loadingSync = false;
|
||||
|
||||
const updateStatus = await check();
|
||||
@ -72,19 +89,80 @@
|
||||
`[FanslySync::page_init:home] App and Tauri versions fetched. We are running App version: ${versionData.appVersion}, atop Tauri version: ${versionData.tauriVersion}`
|
||||
);
|
||||
|
||||
info(`[FanslySync::page_init:home] Setting up autosync interval...`);
|
||||
syncInterval = setInterval(
|
||||
async () => {
|
||||
if (config?.auto_sync_enabled) {
|
||||
info(`[FanslySync::autoSyncProcess] Auto Sync enabled - syncing data automatically.`);
|
||||
const nextIntervalTime = new Date(
|
||||
Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||
);
|
||||
const nextIntervalTimeString = nextIntervalTime.toLocaleTimeString();
|
||||
const returnedData = await syncNow(true);
|
||||
if (!returnedData || returnedData === null) {
|
||||
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||
|
||||
// Send error notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Auto Sync Failed!',
|
||||
body: `An error occurred while syncing data automatically. We will automatically retry at ${nextIntervalTimeString}.`
|
||||
});
|
||||
} else {
|
||||
info(
|
||||
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||
);
|
||||
|
||||
const [_, uploadErr] = await awaiter(
|
||||
invoke('fansly_upload_auto_sync_data', {
|
||||
token: config?.sync_token,
|
||||
data: returnedData
|
||||
})
|
||||
);
|
||||
|
||||
if (uploadErr) {
|
||||
error(
|
||||
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||
);
|
||||
|
||||
// Send error notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Auto Sync Failed!',
|
||||
body: `An error occurred while uploading data to the server. We will automatically retry at ${nextIntervalTimeString}.`
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Send success notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Auto Sync Successful!',
|
||||
body: `Data synced and uploaded successfully. Next sync will occur at ${nextIntervalTimeString}.`
|
||||
});
|
||||
}
|
||||
} else {
|
||||
info(`[FanslySync::autoSyncProcess] Auto Sync disabled - skipping this sync.`);
|
||||
}
|
||||
},
|
||||
(config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||
);
|
||||
|
||||
info(`[FanslySync::page_init:home] Autosync interval set successfully.`);
|
||||
info(`[FanslySync::page_init:home] Page initialization completed successfully.`);
|
||||
});
|
||||
|
||||
async function syncNow() {
|
||||
async function syncNow(auto: boolean = false) {
|
||||
info(`[FanslySync::syncNow] Starting manual sync...`);
|
||||
|
||||
syncState.error = false;
|
||||
syncState.success = false;
|
||||
syncState.syncing = true;
|
||||
syncState.show = true;
|
||||
syncState.show = !auto;
|
||||
|
||||
const [syncData, syncError] = await awaiter(invoke('fansly_sync') as Promise<SyncData>);
|
||||
console.log(syncData, syncError);
|
||||
const [syncData, syncError] = await awaiter(
|
||||
invoke('fansly_sync', {
|
||||
auto
|
||||
}) as Promise<SyncData>
|
||||
);
|
||||
|
||||
if (syncError || syncData === null) {
|
||||
error(
|
||||
@ -93,6 +171,13 @@
|
||||
syncState.syncing = false;
|
||||
syncState.error = true;
|
||||
syncState.message = syncError ?? 'Sync data was null';
|
||||
|
||||
// Send failure notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Sync Failed!',
|
||||
body: 'An error occurred while syncing data. Please check the app for more details.'
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,6 +195,12 @@
|
||||
syncState.syncing = false;
|
||||
syncState.error = true;
|
||||
syncState.message = saveConfigError ?? 'Save config data was null';
|
||||
|
||||
// Send failure notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Sync Failed!',
|
||||
body: 'An error occurred while syncing data. Please check the app for more details.'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -127,6 +218,7 @@
|
||||
soundName = 'completion-sucess';
|
||||
}
|
||||
|
||||
if (!auto)
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Sync Successful!',
|
||||
body: 'Data synced successfully. Please look at the app for more details.',
|
||||
@ -134,6 +226,9 @@
|
||||
});
|
||||
|
||||
info(`[FanslySync::syncNow] Manual sync completed successfully.`);
|
||||
|
||||
if (auto) return syncData;
|
||||
else return null;
|
||||
}
|
||||
|
||||
async function doUpdate() {
|
||||
@ -162,13 +257,357 @@
|
||||
console.log('User declined update');
|
||||
}
|
||||
}
|
||||
|
||||
async function enableAutoSync() {
|
||||
const isAutoStartEnabled = await isEnabled();
|
||||
|
||||
if (!isAutoStartEnabled) {
|
||||
// Required to enable autosync. Ask user for permission
|
||||
const confirm = await ask(
|
||||
`We've detected that FanslySync is not set to start automatically with the system. To enable Auto Sync, we need to enable this feature. Would you like to enable this feature now?`,
|
||||
{
|
||||
title: 'FanslySync | Enable Auto Start',
|
||||
okLabel: 'Yes',
|
||||
cancelLabel: 'No',
|
||||
kind: 'warning'
|
||||
}
|
||||
);
|
||||
|
||||
if (!confirm) {
|
||||
// Error out
|
||||
await message(
|
||||
`Auto Sync cannot be enabled without enabling the Auto Start feature. Please enable the Auto Start feature and try again.`,
|
||||
{ title: 'FanslySync | Auto Sync Error', kind: 'error' }
|
||||
);
|
||||
|
||||
return;
|
||||
} else {
|
||||
await toast.promise(enable(), {
|
||||
loading: 'Enabling Auto Start...',
|
||||
success: 'Auto Start enabled successfully.',
|
||||
error: 'Failed to enable Auto Start. Please try again.'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure they have a sync token set
|
||||
if (!config?.sync_token || config?.sync_token.length === 0) {
|
||||
await message(
|
||||
`Auto Sync cannot be enabled without a valid sync token. Please set a sync token in settings and try again.`,
|
||||
{ title: 'FanslySync | Auto Sync Error', kind: 'error' }
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable autosync
|
||||
config!.auto_sync_enabled = !config?.auto_sync_enabled;
|
||||
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||
|
||||
if (saveConfigError) {
|
||||
await message(
|
||||
`Failed to save Auto Sync configuration. Please try again. Error: ${saveConfigError}`,
|
||||
{ title: 'FanslySync | Auto Sync Error', kind: 'error' }
|
||||
);
|
||||
error(
|
||||
`[FanslySync::enableAutoSync] Failed to save Auto Sync configuration. Error: ${saveConfigError}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear interval if autosync is disabled, set if enabled
|
||||
if (config?.auto_sync_enabled) {
|
||||
syncInterval = setInterval(
|
||||
async () => {
|
||||
if (config?.auto_sync_enabled) {
|
||||
info(`[FanslySync::autoSyncProcess] Auto Sync enabled - syncing data automatically.`);
|
||||
const nextIntervalTime = new Date(
|
||||
Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||
);
|
||||
const nextIntervalTimeString = nextIntervalTime.toLocaleTimeString();
|
||||
const returnedData = await syncNow(true);
|
||||
if (!returnedData || returnedData === null) {
|
||||
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||
|
||||
// Send error notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Auto Sync Failed!',
|
||||
body: `An error occurred while syncing data automatically. We will automatically retry at ${nextIntervalTimeString}.`
|
||||
});
|
||||
} else {
|
||||
info(
|
||||
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||
);
|
||||
|
||||
const [_, uploadErr] = await awaiter(
|
||||
invoke('fansly_upload_auto_sync_data', {
|
||||
token: config?.sync_token,
|
||||
data: returnedData
|
||||
})
|
||||
);
|
||||
|
||||
if (uploadErr) {
|
||||
error(
|
||||
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||
);
|
||||
|
||||
// Send error notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Auto Sync Failed!',
|
||||
body: `An error occurred while uploading data to the server. We will automatically retry at ${nextIntervalTimeString}.`
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Send success notification
|
||||
await sendNotification({
|
||||
title: 'FanslySync: Auto Sync Successful!',
|
||||
body: `Data synced and uploaded successfully. Next sync will occur at ${nextIntervalTimeString}.`
|
||||
});
|
||||
}
|
||||
} else {
|
||||
info(`[FanslySync::autoSyncProcess] Auto Sync disabled - skipping this sync.`);
|
||||
}
|
||||
},
|
||||
(config?.sync_interval ?? 1) * 60 * 60 * 1000
|
||||
);
|
||||
|
||||
// Run a auto sync as soon as it's enabled
|
||||
const returnedData = await syncNow(true);
|
||||
if (!returnedData || returnedData === null) {
|
||||
error(`[FanslySync::autoSyncProcess] Failed to sync data automatically.`);
|
||||
// Disable autosync, resave, and error out on the UI
|
||||
config!.auto_sync_enabled = false;
|
||||
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||
|
||||
if (saveConfigError)
|
||||
toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||
duration: 5000
|
||||
});
|
||||
|
||||
toast.error(
|
||||
'Self test of Auto Sync failed (SYNC_ERR). Please check the logs for more details.',
|
||||
{
|
||||
duration: 5000
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
} else {
|
||||
info(
|
||||
`[FanslySync::autoSyncProcess] Synced data automatically - preparing to send to server.`
|
||||
);
|
||||
|
||||
const [_, uploadErr] = await awaiter(
|
||||
invoke('fansly_upload_auto_sync_data', {
|
||||
token: config?.sync_token,
|
||||
data: returnedData
|
||||
})
|
||||
);
|
||||
|
||||
if (uploadErr) {
|
||||
error(
|
||||
`[FanslySync::autoSyncProcess] Failed to upload data to server. Error: ${uploadErr}`
|
||||
);
|
||||
|
||||
// Disable autosync, resave, and error out on the UI
|
||||
config!.auto_sync_enabled = false;
|
||||
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||
if (saveConfigError)
|
||||
toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||
duration: 5000
|
||||
});
|
||||
|
||||
toast.error(
|
||||
'Self test of Auto Sync failed (UPLOAD_ERR). Please check the logs for more details.',
|
||||
{
|
||||
duration: 5000
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (syncInterval) {
|
||||
clearInterval(syncInterval);
|
||||
}
|
||||
}
|
||||
|
||||
info(`[FanslySync::enableAutoSync] Auto Sync configuration saved successfully.`);
|
||||
const nextInterval = new Date(Date.now() + (config?.sync_interval ?? 1) * 60 * 60 * 1000);
|
||||
const nextIntervalString = nextInterval.toLocaleTimeString();
|
||||
|
||||
toast.success(
|
||||
`${
|
||||
config?.auto_sync_enabled ? 'Enabled' : 'Disabled'
|
||||
} Auto Sync successfully. ${config?.auto_sync_enabled ? `The next sync will occur at ${nextIntervalString}.` : ''}`,
|
||||
{
|
||||
duration: 5000
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function onSyncTokenEntered() {
|
||||
// Check if the sync token is valid
|
||||
autoSyncConfigState.validatingToken = true;
|
||||
|
||||
const [_, tokenError] = await awaiter(
|
||||
invoke('fansly_check_sync_token', { token: autoSyncConfig.syncToken })
|
||||
);
|
||||
|
||||
if (tokenError) {
|
||||
error(`[FanslySync::onSyncTokenEntered] Failed to validate sync token. Error: ${tokenError}`);
|
||||
autoSyncConfigState.validatingToken = false;
|
||||
autoSyncConfigState.tokenValid = false;
|
||||
canSave = false;
|
||||
return;
|
||||
} else {
|
||||
info(`[FanslySync::onSyncTokenEntered] Sync token validated successfully.`);
|
||||
autoSyncConfigState.validatingToken = false;
|
||||
autoSyncConfigState.tokenValid = true;
|
||||
canSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
async function onAutoSyncSave() {
|
||||
// Close the modal
|
||||
isAutoSyncConfigModalOpen = false;
|
||||
|
||||
const savingToast = await toast.loading('Saving Auto Sync configuration...');
|
||||
|
||||
config!.sync_interval = autoSyncConfig.interval;
|
||||
config!.sync_token = autoSyncConfig.syncToken;
|
||||
|
||||
const [_, saveConfigError] = await awaiter(invoke('save_config', { config }));
|
||||
|
||||
if (saveConfigError) {
|
||||
await toast.error('Failed to save Auto Sync configuration. Please try again.', {
|
||||
id: savingToast
|
||||
});
|
||||
error(
|
||||
`[FanslySync::onAutoSyncSave] Failed to save Auto Sync configuration. Error: ${saveConfigError}`
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
info(`[FanslySync::onAutoSyncSave] Auto Sync configuration saved successfully.`);
|
||||
await toast.success('Auto Sync configuration saved successfully.', { id: savingToast });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container bg-zinc-800 w-screen h-screen">
|
||||
<!-- Top header, Bambu Connect at the left side, settings icon on the right -->
|
||||
<!-- Create config modal -->
|
||||
{#if isAutoSyncConfigModalOpen}
|
||||
<div
|
||||
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-10"
|
||||
transition:fade={{ duration: 300 }}
|
||||
>
|
||||
<div
|
||||
class="bg-zinc-900 p-4 rounded-lg"
|
||||
in:fly={{ y: 20, duration: 300 }}
|
||||
out:fly={{ y: 20, duration: 200 }}
|
||||
>
|
||||
<h1 class="text-2xl font-bold text-gray-200">Auto Sync Configuration</h1>
|
||||
<p class="text-gray-400 mt-1">
|
||||
Configure the Auto Sync feature here. Please ensure you have a valid sync token set in
|
||||
settings.
|
||||
</p>
|
||||
<div class="flex flex-col mt-2">
|
||||
<label for="syncInterval" class="text-gray-200">Sync Interval (in hours)</label>
|
||||
<input
|
||||
type="number"
|
||||
id="syncInterval"
|
||||
class="bg-zinc-700 text-gray-200 p-2 rounded-lg mt-1"
|
||||
placeholder="Enter sync interval in hours"
|
||||
bind:value={autoSyncConfig.interval}
|
||||
min="1"
|
||||
/>
|
||||
<p class="text-gray-400 mt-1">
|
||||
How often should the app sync data automatically? Please enter a number in hours. The
|
||||
minimum value is 1 hour.
|
||||
</p>
|
||||
<label for="syncToken" class="text-gray-200 mt-2">Sync Token</label>
|
||||
<div class="relative flex items-center">
|
||||
<!-- Sync token input. Check in the input for valid token, x not, question mark empty -->
|
||||
<input
|
||||
type="text"
|
||||
id="syncToken"
|
||||
class="bg-zinc-700 text-gray-200 p-2 rounded-lg mt-1 w-full pr-10"
|
||||
placeholder="Enter sync token"
|
||||
bind:value={autoSyncConfig.syncToken}
|
||||
on:change={onSyncTokenEntered}
|
||||
/>
|
||||
{#if !autoSyncConfigState.validatingToken && autoSyncConfigState.tokenValid}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="absolute right-2 bottom-2 w-6 h-6 text-green-500"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
{:else if !autoSyncConfigState.validatingToken && !autoSyncConfigState.tokenValid}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="absolute right-2 bottom-2 w-6 h-6 text-red-500"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
{:else if autoSyncConfigState.validatingToken}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="absolute right-2 bottom-2 w-6 h-6 text-gray-400 animate-spin"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="text-gray-400 mt-1">
|
||||
Unfocus (click out of) the input to validate the token. A green checkmark means the
|
||||
token is valid.
|
||||
</p>
|
||||
<div class="flex mt-2">
|
||||
<button
|
||||
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full disabled:opacity-50 disabled:cursor-not-allowed hover:bg-blue-700 transition-all duration-200 ease-in-out"
|
||||
disabled={!canSave}
|
||||
on:click={onAutoSyncSave}
|
||||
>
|
||||
{canSave ? 'Save' : 'Please enter a valid sync token'}
|
||||
</button>
|
||||
<button
|
||||
class="bg-red-500 text-white px-4 py-2 rounded-lg w-full ml-2 disabled:opacity-50 disabled:cursor-not-allowed hover:bg-red-600 transition-all duration-200 ease-in-out"
|
||||
on:click={() => {
|
||||
isAutoSyncConfigModalOpen = false;
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Top header, FanslySync at the left side, settings icon on the right -->
|
||||
<div class="flex justify-between items-center h-16 px-4 bg-zinc-900">
|
||||
<div class="flex items-center">
|
||||
<img src="/fanslySync.png" alt="FanslySynct" class="w-8 h-8" />
|
||||
<img src="/fanslySync.png" alt="FanslySync" class="w-8 h-8" />
|
||||
<h1 class="text-2xl font-bold text-gray-200 ml-2">FanslySync</h1>
|
||||
<span class="text-gray-400 ml-2"
|
||||
>v{versionData.appVersion} (runtime: {versionData.tauriVersion})</span
|
||||
@ -240,40 +679,54 @@
|
||||
<!-- Automatic sync card -->
|
||||
<div class="relative">
|
||||
<div class="bg-zinc-700 p-4 rounded-lg">
|
||||
<div class="flex items-center space-x-2">
|
||||
<h1 class="text-xl font-bold text-gray-200">Automatic Sync</h1>
|
||||
<!-- Status badge -->
|
||||
<span
|
||||
class={`px-2 py-1 rounded-lg text-xs font-bold ${
|
||||
config?.auto_sync_enabled ? 'bg-green-500' : 'bg-red-500'
|
||||
}`}
|
||||
>
|
||||
{config?.auto_sync_enabled ? 'Enabled' : 'Disabled'}
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-gray-400 mt-1">
|
||||
Sync content automatically every {config?.sync_interval} hours. Please ensure you have
|
||||
a stable internet connection.
|
||||
Sync content automatically every {config?.sync_interval}
|
||||
{(config?.sync_interval ?? 0 > 1) ? 'hour' : 'hours'}. Please ensure you have a
|
||||
stable internet connection.
|
||||
</p>
|
||||
<div class="flex mt-2">
|
||||
<button
|
||||
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full"
|
||||
on:click={() => console.log('Automatic sync clicked')}
|
||||
class={` text-white px-4 py-2 rounded-lg w-full ${
|
||||
!config?.auto_sync_enabled
|
||||
? 'bg-green-500 hover:bg-green-600'
|
||||
: 'bg-red-500 hover:bg-red-600'
|
||||
} disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 ease-in-out`}
|
||||
on:click={enableAutoSync}
|
||||
disabled={syncState.syncing}
|
||||
>
|
||||
Enable
|
||||
{syncState.syncing
|
||||
? 'Sync in progress. Please wait.'
|
||||
: config?.auto_sync_enabled
|
||||
? 'Disable'
|
||||
: 'Enable'}
|
||||
{!syncState.syncing ? 'Auto Sync' : ''}
|
||||
</button>
|
||||
<button
|
||||
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full ml-2 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 ease-in-out hover:bg-blue-700"
|
||||
on:click={() => {
|
||||
isAutoSyncConfigModalOpen = true;
|
||||
}}
|
||||
disabled={config?.auto_sync_enabled || syncState.syncing}
|
||||
>
|
||||
{syncState.syncing
|
||||
? 'Sync in progress. Please wait.'
|
||||
: config?.auto_sync_enabled
|
||||
? 'Disable Auto Sync To Edit'
|
||||
: 'Edit Auto Sync Configuration'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="absolute top-0 left-0 right-0 bottom-0 bg-white/30 backdrop-blur-sm flex flex-col justify-center items-center rounded-lg"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="size-10 text-blue-400"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
|
||||
/>
|
||||
</svg>
|
||||
<h1 class="text-xl font-bold text-gray-200 ml-2">Automatic Sync is coming soon!</h1>
|
||||
<p class="text-white mt-1">Stay tuned for updates.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Manual sync card -->
|
||||
@ -285,7 +738,9 @@
|
||||
<div class="flex mt-2">
|
||||
<button
|
||||
class="bg-blue-600 text-white px-4 py-2 rounded-lg w-full disabled:opacity-50 disabled:cursor-not-allowed hover:bg-blue-700 transition-all duration-200 ease-in-out"
|
||||
on:click={syncNow}
|
||||
on:click={() => {
|
||||
syncNow(false);
|
||||
}}
|
||||
disabled={syncState.syncing}
|
||||
>
|
||||
{syncState.syncing ? 'Syncing...' : 'Sync Now'}
|
||||
|
2
src/routes/home/debug.log
Normal file
2
src/routes/home/debug.log
Normal file
@ -0,0 +1,2 @@
|
||||
[0813/143825.367:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
[0813/143918.868:ERROR:registration_protocol_win.cc(108)] CreateFile: The system cannot find the file specified. (0x2)
|
Loading…
x
Reference in New Issue
Block a user