diff --git a/.github/workflows/deployment.yaml b/.github/workflows/deployment.yaml
index 1d6cdf02..f9b2e529 100644
--- a/.github/workflows/deployment.yaml
+++ b/.github/workflows/deployment.yaml
@@ -9,7 +9,7 @@ jobs:
strategy:
matrix: # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs
platform: [mac, ios]
- runs-on: macos-latest # https://github.com/actions/runner-images
+ runs-on: macos-26 # https://github.com/actions/runner-images
steps:
- uses: actions/checkout@v4 # https://github.com/actions/checkout
with:
@@ -37,8 +37,10 @@ jobs:
if: ${{ github.event.release.prerelease }}
- run: npm run build:${{ matrix.platform }}-safari-15
if: ${{ ! github.event.release.prerelease }}
- - name: Set xcode version
- run: sudo xcode-select -s "/Applications/Xcode_16.2.app" # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md#xcode
+ # - name: Set xcode version
+ # run: sudo xcode-select -s "/Applications/Xcode_26.1.1.app" # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md#xcode
+ # - run: xcodebuild -downloadPlatform iOS # Temporary fix for Xcode_26_beta
+ # if: matrix.platform == 'ios'
- name: Run fastlane
id: fastlane
working-directory: ./fastlane
diff --git a/README.md b/README.md
index d0601bfc..09cdc78a 100644
--- a/README.md
+++ b/README.md
@@ -54,9 +54,9 @@ After installing the iOS App, you need two main steps to make the extension work
> [!NOTE]
>
-> The App cannot detect whether you have enabled the extension in Safari, therefore, the App prompt will not change after you enable the extension. Currently the App interface is only used to set or change the userscripts directory.
+> The iOS App cannot detect whether you have enabled the extension in Safari, therefore, the App prompt will not change after you enable the extension. Currently the App interface is only used to set or change the userscripts directory.
>
-> You could select an iCloud folder for syncing scripts between macOS and iOS, but please note that there may be delays in synchronization, and you may encounter files be evictioned due to iCloud optimization, please refer to [#424](https://github.com/quoid/userscripts/issues/424).
+> You could select an iCloud folder for syncing scripts between macOS and iOS, but please note that there may be delays in synchronization, and you may encounter files be evictioned due to iCloud optimization, please refer to [#424](https://github.com/quoid/userscripts/issues/424). (**Since macOS 15 / iOS 18, please set "keep downloaded" for the folder to avoid eviction**)
There are two main ways to install a user script from the iOS version:
@@ -386,6 +386,6 @@ Userscripts does not collect any data from its users nor monitor activities or a
## License
-Copyright (c) 2018-2024 Justin Wasack
+Copyright © 2018-2025 Justin Wasack
Licensed under the [GNU General Public License v3.0](/LICENSE) license for all open source applications. A commercial license is required for all other applications.
diff --git a/docs/contributing.md b/docs/contributing.md
index 7d09d9d4..3cb92e9d 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -117,4 +117,4 @@ If you are not a member of the project, first you need to fork the master branch
# About
-[Userscripts](https://github.com/quoid/userscripts) @ 2018-2023
+[Userscripts](https://github.com/quoid/userscripts)
diff --git a/docs/dev.md b/docs/dev.md
index 2bfa7681..262aac05 100644
--- a/docs/dev.md
+++ b/docs/dev.md
@@ -79,4 +79,4 @@ Note that all existing `.xcconfig` files already include `.dev.xcconfig` files o
# About
-[Userscripts](https://github.com/quoid/userscripts) @ 2018-2024
+[Userscripts](https://github.com/quoid/userscripts)
diff --git a/docs/structure.md b/docs/structure.md
index d493c3b7..1a0cd320 100644
--- a/docs/structure.md
+++ b/docs/structure.md
@@ -38,4 +38,4 @@ Build the project from here to extension bundled app
# About
-[Userscripts](https://github.com/quoid/userscripts) @ 2018-2023
+[Userscripts](https://github.com/quoid/userscripts)
diff --git a/fastlane/Gemfile.lock b/fastlane/Gemfile.lock
index 989cb342..c6013a88 100644
--- a/fastlane/Gemfile.lock
+++ b/fastlane/Gemfile.lock
@@ -1,39 +1,40 @@
GEM
remote: https://rubygems.org/
specs:
- CFPropertyList (3.0.7)
- base64
- nkf
- rexml
- addressable (2.8.7)
- public_suffix (>= 2.0.2, < 7.0)
+ CFPropertyList (3.0.8)
+ abbrev (0.1.2)
+ addressable (2.8.8)
+ public_suffix (>= 2.0.2, < 8.0)
artifactory (3.0.17)
atomos (0.1.3)
- aws-eventstream (1.3.2)
- aws-partitions (1.1106.0)
- aws-sdk-core (3.224.0)
+ aws-eventstream (1.4.0)
+ aws-partitions (1.1188.0)
+ aws-sdk-core (3.239.2)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
+ bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
- aws-sdk-kms (1.101.0)
- aws-sdk-core (~> 3, >= 3.216.0)
+ aws-sdk-kms (1.118.0)
+ aws-sdk-core (~> 3, >= 3.239.1)
aws-sigv4 (~> 1.5)
- aws-sdk-s3 (1.186.1)
- aws-sdk-core (~> 3, >= 3.216.0)
+ aws-sdk-s3 (1.205.0)
+ aws-sdk-core (~> 3, >= 3.234.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
- aws-sigv4 (1.11.0)
+ aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
+ bigdecimal (3.3.1)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
+ csv (3.3.5)
declarative (0.0.20)
digest-crc (0.7.0)
rake (>= 12.0.0, < 14.0.0)
@@ -53,14 +54,14 @@ GEM
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
- faraday-cookie_jar (0.0.7)
+ faraday-cookie_jar (0.0.8)
faraday (>= 0.8.0)
- http-cookie (~> 1.0.0)
+ http-cookie (>= 1.0.0)
faraday-em_http (1.0.0)
- faraday-em_synchrony (1.0.0)
+ faraday-em_synchrony (1.0.1)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
- faraday-multipart (1.1.0)
+ faraday-multipart (1.1.1)
multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
@@ -70,15 +71,18 @@ GEM
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.0)
- fastlane (2.227.2)
+ fastlane (2.229.1)
CFPropertyList (>= 2.3, < 4.0.0)
+ abbrev (~> 0.1.2)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
+ base64 (~> 0.2.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
+ csv (~> 3.3)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
@@ -98,7 +102,9 @@ GEM
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
+ mutex_m (~> 0.3.0)
naturally (~> 2.2)
+ nkf (~> 0.2.0)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
@@ -157,37 +163,37 @@ GEM
httpclient (2.9.0)
mutex_m
jmespath (1.6.2)
- json (2.12.0)
- jwt (2.10.1)
+ json (2.16.0)
+ jwt (2.10.2)
base64
logger (1.7.0)
mini_magick (4.13.2)
mini_mime (1.1.5)
- multi_json (1.15.0)
+ multi_json (1.17.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
- naturally (2.2.1)
+ naturally (2.3.0)
nkf (0.2.0)
- optparse (0.6.0)
+ optparse (0.8.0)
os (1.1.4)
plist (3.7.2)
- public_suffix (6.0.2)
- rake (13.2.1)
+ public_suffix (7.0.0)
+ rake (13.3.1)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
- rexml (3.4.1)
+ rexml (3.4.4)
rouge (3.28.0)
ruby2_keywords (0.0.5)
rubyzip (2.4.1)
security (0.1.5)
- signet (0.20.0)
+ signet (0.21.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
- jwt (>= 1.5, < 3.0)
+ jwt (>= 1.5, < 4.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
@@ -217,11 +223,11 @@ GEM
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
- arm64-darwin-23
+ arm64-darwin-25
ruby
DEPENDENCIES
fastlane
BUNDLED WITH
- 2.6.9
+ 2.7.2
diff --git a/public/ext/shared/_locales/en/messages.json b/public/ext/shared/_locales/en/messages.json
index a39bfc24..c17c6cad 100644
--- a/public/ext/shared/_locales/en/messages.json
+++ b/public/ext/shared/_locales/en/messages.json
@@ -85,6 +85,24 @@
"settings_global_active_desc": {
"message": "Toggle on/off script injection for the pages you visit"
},
+ "settings_theme_mode": {
+ "message": "Theme mode"
+ },
+ "settings_theme_mode_desc": {
+ "message": "Toggle theme mode"
+ },
+ "settings_theme_mode_auto": {
+ "message": "Auto (System)"
+ },
+ "settings_theme_mode_dark": {
+ "message": "Dark"
+ },
+ "settings_theme_mode_light": {
+ "message": "Light"
+ },
+ "settings_theme_mode_custom": {
+ "message": "Custom"
+ },
"settings_global_exclude_match": {
"message": "Global Exclude Match patterns"
},
diff --git a/scripts/dev-safari.js b/scripts/dev-safari.js
index 34943850..c9236b9f 100644
--- a/scripts/dev-safari.js
+++ b/scripts/dev-safari.js
@@ -186,6 +186,7 @@ async function serverCheck(url) {
/** run development server */
const server = await createServer({
...sharedConfig,
+ publicDir: "public/ext/vendor/",
plugins: [svelte()],
server: {
host: true,
diff --git a/src/app/App.svelte b/src/app/App.svelte
index 7e6c5c5b..bbfe8df8 100644
--- a/src/app/App.svelte
+++ b/src/app/App.svelte
@@ -1,7 +1,7 @@
@@ -72,10 +108,30 @@
{/if}
{/if}
-
-
-
+
+ {#if !sidebarHidden}
+
+
+ {/if}
+
+{#if splitterActive}
+
+{/if}
{#each $notifications as item (item.id)}
notifications.remove(item.id)} {item} />
@@ -120,6 +176,34 @@
overflow: hidden;
}
+ .resize-mask {
+ background-color: transparent;
+ cursor: col-resize;
+ position: fixed;
+ inset: 0;
+ z-index: 20;
+ }
+
+ .splitter {
+ --splitter-width: 6px;
+ --splitter-offset: calc(var(--splitter-width) / 2);
+ --sidebar-fixed-width: max(var(--sidebar-min-width), var(--sidebar-width));
+
+ background-color: transparent;
+ cursor: col-resize;
+ position: fixed;
+ left: calc(var(--sidebar-fixed-width) - var(--splitter-offset));
+ width: var(--splitter-width);
+ height: 100svh;
+ z-index: 21;
+ transition: background-color 0.2s ease-in-out;
+
+ &:hover,
+ &.dragging {
+ background-color: var(--color-blue);
+ }
+ }
+
ul {
bottom: 1rem;
left: 50%;
diff --git a/src/ext/extension-page/Components/Editor/CodeMirror.svelte b/src/ext/extension-page/Components/Editor/CodeMirror.svelte
index f097189b..b2cbacda 100644
--- a/src/ext/extension-page/Components/Editor/CodeMirror.svelte
+++ b/src/ext/extension-page/Components/Editor/CodeMirror.svelte
@@ -150,11 +150,6 @@
"Cmd-S": () => saveHandler(),
"Cmd-F": () => activateSearch(),
Esc: () => (searchActive = false),
- Tab: (cm) => {
- // convert tabs to spaces and add invisible elements
- const s = Array(cm.getOption("indentUnit") + 1).join(" ");
- cm.replaceSelection(s);
- },
},
});
diff --git a/src/ext/extension-page/Components/Editor/Editor.svelte b/src/ext/extension-page/Components/Editor/Editor.svelte
index 0bdd3507..e0b7c719 100644
--- a/src/ext/extension-page/Components/Editor/Editor.svelte
+++ b/src/ext/extension-page/Components/Editor/Editor.svelte
@@ -13,6 +13,10 @@
import iconDownload from "@shared/img/icon-download.svg?raw";
import iconTrash from "@shared/img/icon-trash.svg?raw";
import iconSync from "@shared/img/icon-sync.svg?raw";
+ import iconSidebar from "@shared/img/icon-sidebar.svg?raw";
+
+ export let sidebarHidden;
+ export let sidebarSwitch;
// the data the populates editor elements
let canUpdate;
@@ -167,13 +171,22 @@
No Item Selected
{/if}