@necrolab/dashboard 0.4.221 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +27 -1
- package/.vscode/extensions.json +1 -1
- package/README.md +64 -2
- package/artwork/image.png +0 -0
- package/backend/api.js +26 -24
- package/backend/auth.js +2 -2
- package/backend/batching.js +1 -1
- package/backend/endpoints.js +8 -11
- package/backend/index.js +2 -2
- package/backend/mock-data.js +27 -36
- package/backend/mock-src/classes/logger.js +5 -7
- package/backend/mock-src/classes/utils.js +3 -2
- package/backend/mock-src/ticketmaster.js +4 -4
- package/backend/validator.js +2 -2
- package/config/configs.json +0 -1
- package/dev-server.js +134 -0
- package/exit +209 -0
- package/index.html +80 -8
- package/index.js +1 -1
- package/jsconfig.json +16 -0
- package/package.json +39 -25
- package/postcss.config.js +1 -1
- package/postinstall.js +124 -20
- package/public/android-chrome-192x192.png +0 -0
- package/public/android-chrome-512x512.png +0 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/favicon-16x16.png +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/img/logo_trans.png +0 -0
- package/public/img/necro_logo.png +0 -0
- package/public/manifest.json +16 -10
- package/public/reconnect-logo.png +0 -0
- package/run +176 -9
- package/src/App.vue +498 -85
- package/src/assets/css/base/reset.scss +43 -0
- package/src/assets/css/base/scroll.scss +114 -0
- package/src/assets/css/base/typography.scss +37 -0
- package/src/assets/css/components/buttons.scss +216 -0
- package/src/assets/css/components/forms.scss +221 -0
- package/src/assets/css/components/modals.scss +13 -0
- package/src/assets/css/components/tables.scss +27 -0
- package/src/assets/css/components/toasts.scss +100 -0
- package/src/assets/css/main.scss +202 -122
- package/src/assets/img/background.svg +2 -2
- package/src/assets/img/background.svg.backup +11 -0
- package/src/assets/img/logo_trans.png +0 -0
- package/src/components/Auth/LoginForm.vue +95 -11
- package/src/components/Editors/Account/Account.vue +116 -40
- package/src/components/Editors/Account/AccountCreator.vue +88 -39
- package/src/components/Editors/Account/AccountView.vue +102 -34
- package/src/components/Editors/Account/CreateAccount.vue +80 -32
- package/src/components/Editors/Profile/CreateProfile.vue +269 -83
- package/src/components/Editors/Profile/Profile.vue +132 -47
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +82 -20
- package/src/components/Editors/Profile/ProfileView.vue +89 -32
- package/src/components/Editors/TagLabel.vue +67 -6
- package/src/components/Editors/TagToggle.vue +7 -2
- package/src/components/Filter/Filter.vue +288 -71
- package/src/components/Filter/FilterPreview.vue +202 -31
- package/src/components/Filter/PriceSortToggle.vue +76 -6
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Row.vue +1 -1
- package/src/components/Table/Table.vue +19 -2
- package/src/components/Tasks/CheckStock.vue +6 -8
- package/src/components/Tasks/Controls/DesktopControls.vue +27 -17
- package/src/components/Tasks/Controls/MobileControls.vue +8 -45
- package/src/components/Tasks/CreateTaskAXS.vue +80 -72
- package/src/components/Tasks/CreateTaskTM.vue +95 -141
- package/src/components/Tasks/MassEdit.vue +4 -6
- package/src/components/Tasks/QuickSettings.vue +199 -30
- package/src/components/Tasks/ScrapeVenue.vue +5 -6
- package/src/components/Tasks/Stats.vue +50 -24
- package/src/components/Tasks/Task.vue +384 -179
- package/src/components/Tasks/TaskLabel.vue +2 -2
- package/src/components/Tasks/TaskView.vue +136 -48
- package/src/components/Tasks/Utilities.vue +25 -10
- package/src/components/Tasks/ViewTask.vue +321 -0
- package/src/components/icons/Bag.vue +1 -1
- package/src/components/icons/Check.vue +5 -0
- package/src/components/icons/Close.vue +21 -0
- package/src/components/icons/CloseX.vue +5 -0
- package/src/components/icons/Eye.vue +6 -0
- package/src/components/icons/Key.vue +21 -0
- package/src/components/icons/Loyalty.vue +1 -1
- package/src/components/icons/Mail.vue +2 -2
- package/src/components/icons/Pencil.vue +21 -0
- package/src/components/icons/Play.vue +2 -2
- package/src/components/icons/Profile.vue +18 -0
- package/src/components/icons/Reload.vue +4 -5
- package/src/components/icons/Sandclock.vue +2 -2
- package/src/components/icons/Sell.vue +21 -0
- package/src/components/icons/Spinner.vue +42 -0
- package/src/components/icons/SquareCheck.vue +18 -0
- package/src/components/icons/SquareUncheck.vue +18 -0
- package/src/components/icons/Stadium.vue +1 -1
- package/src/components/icons/Wildcard.vue +18 -0
- package/src/components/icons/index.js +26 -1
- package/src/components/ui/Modal.vue +107 -13
- package/src/components/ui/Navbar.vue +175 -40
- package/src/components/ui/ReconnectIndicator.vue +351 -55
- package/src/components/ui/Splash.vue +5 -35
- package/src/components/ui/controls/CountryChooser.vue +200 -62
- package/src/components/ui/controls/atomic/Checkbox.vue +119 -10
- package/src/components/ui/controls/atomic/Dropdown.vue +216 -39
- package/src/components/ui/controls/atomic/LoadingButton.vue +45 -0
- package/src/components/ui/controls/atomic/MultiDropdown.vue +300 -37
- package/src/components/ui/controls/atomic/Switch.vue +53 -25
- package/src/composables/useClickOutside.js +21 -0
- package/src/composables/useDropdownPosition.js +174 -0
- package/src/libs/Filter.js +60 -24
- package/src/registerServiceWorker.js +1 -1
- package/src/stores/connection.js +4 -4
- package/src/stores/sampleData.js +172 -199
- package/src/stores/ui.js +55 -20
- package/src/stores/utils.js +30 -4
- package/src/types/index.js +41 -0
- package/src/utils/debug.js +1 -0
- package/src/views/Accounts.vue +116 -50
- package/src/views/Console.vue +394 -77
- package/src/views/Editor.vue +1176 -123
- package/src/views/FilterBuilder.vue +528 -250
- package/src/views/Login.vue +75 -14
- package/src/views/Profiles.vue +119 -34
- package/src/views/Tasks.vue +266 -98
- package/static/offline.html +192 -50
- package/switch-branch.sh +41 -0
- package/tailwind.config.js +119 -27
- package/vite.config.js +73 -16
- package/workbox-config.cjs +63 -0
- package/ICONS.md +0 -21
- package/public/img/background.svg +0 -14
- package/public/img/logo.png +0 -0
- package/public/img/logo_icon.png +0 -0
- package/public/img/logo_icon_2.png +0 -0
- package/src/assets/css/_input.scss +0 -143
- package/src/assets/img/logo.png +0 -0
- package/src/assets/img/logo_icon.png +0 -0
- package/src/assets/img/logo_icon_2.png +0 -0
- package/vue.config.js +0 -32
- package/workbox-config.js +0 -7
package/src/views/Editor.vue
CHANGED
|
@@ -1,122 +1,217 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<!-- Heading -->
|
|
4
|
-
<GearIcon class="w-5 cursor-pointer" @click="ui.toggleModal('quick-settings')" />
|
|
5
4
|
<h4 class="text-white text-xl font-bold mb-5 pt-5 flex gap-2 items-center">
|
|
6
|
-
Editor
|
|
5
|
+
Editor
|
|
6
|
+
<img src="@/assets/img/pencil.svg" />
|
|
7
7
|
</h4>
|
|
8
8
|
|
|
9
|
-
<div class="bg-dark-
|
|
10
|
-
|
|
9
|
+
<div class="bg-dark-400 border border-dark-650 rounded shadow-sm p-2">
|
|
10
|
+
<!-- Admin Editor Section - Hidden when proxy editor is open -->
|
|
11
|
+
<div v-if="ui.profile.admin" class="admin-editor-section" :class="{ 'landscape-hidden': currentProxyList }">
|
|
11
12
|
<h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Admin Editor</h5>
|
|
12
|
-
<div class="
|
|
13
|
-
<
|
|
14
|
-
class="
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
</button>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
<transition name="fade">
|
|
29
|
-
<div v-if="textEditorVisible" class="my-3">
|
|
30
|
-
<!-- Edit -->
|
|
31
|
-
<div class="flex gap-x-4 mb-8">
|
|
13
|
+
<div class="flex-responsive-wrap editor-controls-row">
|
|
14
|
+
<div class="w-full lg:w-64 flex flex-shrink-0 dropdown-container z-dropdown-high">
|
|
15
|
+
<div class="relative flex-grow">
|
|
16
|
+
<Dropdown
|
|
17
|
+
class="bg-dark-500 border-2 border-r-0 border-dark-550 admin-file-dropdown w-full"
|
|
18
|
+
default="Select a file"
|
|
19
|
+
:onClick="(f) => loadFile(f)"
|
|
20
|
+
:options="availableFiles"
|
|
21
|
+
:allowDefault="false"
|
|
22
|
+
:includeAdjacentButtons="true"
|
|
23
|
+
rightAmount="right-1" />
|
|
24
|
+
</div>
|
|
32
25
|
<button
|
|
33
|
-
class="
|
|
34
|
-
@click="
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
<EditIcon />
|
|
26
|
+
class="refresh-button flex items-center justify-center w-10 h-10 text-white bg-dark-400 rounded-r-lg border-2 border-dark-550 border-l-0"
|
|
27
|
+
@click="loadAvailableFiles()"
|
|
28
|
+
title="Refresh file list">
|
|
29
|
+
<ReloadIcon class="refresh-icon" />
|
|
38
30
|
</button>
|
|
31
|
+
</div>
|
|
32
|
+
<!-- Admin editor buttons moved here -->
|
|
33
|
+
<div
|
|
34
|
+
v-if="textEditorVisible"
|
|
35
|
+
class="flex flex-wrap gap-responsive justify-center lg:justify-end editor-buttons-responsive">
|
|
39
36
|
<button
|
|
40
|
-
class="
|
|
41
|
-
@click="
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
37
|
+
class="btn-action flex-shrink-0"
|
|
38
|
+
@click="format()"
|
|
39
|
+
v-if="isJsonFile()"
|
|
40
|
+
title="Format JSON">
|
|
41
|
+
<svg
|
|
42
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
43
|
+
width="16"
|
|
44
|
+
height="16"
|
|
45
|
+
viewBox="0 0 24 24"
|
|
46
|
+
fill="none"
|
|
47
|
+
stroke="currentColor"
|
|
48
|
+
stroke-width="2"
|
|
49
|
+
stroke-linecap="round"
|
|
50
|
+
stroke-linejoin="round">
|
|
51
|
+
<path d="M21 10H7" />
|
|
52
|
+
<path d="M21 6H3" />
|
|
53
|
+
<path d="M21 14H3" />
|
|
54
|
+
<path d="M21 18H7" />
|
|
55
|
+
</svg>
|
|
56
|
+
<span class="hidden sm:inline">Format</span>
|
|
57
|
+
</button>
|
|
58
|
+
<button class="btn-action flex-shrink-0" @click="saveAll" title="Save File">
|
|
59
|
+
<svg
|
|
60
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
61
|
+
width="16"
|
|
62
|
+
height="16"
|
|
63
|
+
viewBox="0 0 24 24"
|
|
64
|
+
fill="none"
|
|
65
|
+
stroke="currentColor"
|
|
66
|
+
stroke-width="2"
|
|
67
|
+
stroke-linecap="round"
|
|
68
|
+
stroke-linejoin="round">
|
|
69
|
+
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
|
70
|
+
<polyline points="17 21 17 13 7 13 7 21" />
|
|
71
|
+
<polyline points="7 3 7 8 15 8" />
|
|
72
|
+
</svg>
|
|
73
|
+
<span class="hidden sm:inline">Save File</span>
|
|
74
|
+
</button>
|
|
75
|
+
<button class="btn-action flex-shrink-0" @click="closeFile" title="Close File">
|
|
76
|
+
<svg
|
|
77
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
78
|
+
width="16"
|
|
79
|
+
height="16"
|
|
80
|
+
viewBox="0 0 24 24"
|
|
81
|
+
fill="none"
|
|
82
|
+
stroke="currentColor"
|
|
83
|
+
stroke-width="2"
|
|
84
|
+
stroke-linecap="round"
|
|
85
|
+
stroke-linejoin="round">
|
|
86
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
87
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
88
|
+
</svg>
|
|
89
|
+
<span class="hidden sm:inline">Close File</span>
|
|
45
90
|
</button>
|
|
46
91
|
</div>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
<transition name="fade">
|
|
95
|
+
<div v-if="textEditorVisible" class="my-3 relative">
|
|
96
|
+
<div class="pb-4">
|
|
97
|
+
<!-- Syntax Highlighting Editor -->
|
|
98
|
+
<div class="editor-container" :class="{ 'has-error': errorMessage }">
|
|
99
|
+
<div class="editor-wrapper">
|
|
100
|
+
<pre ref="codeDisplay" class="language-json code-highlight"></pre>
|
|
101
|
+
<textarea
|
|
102
|
+
ref="codeEditor"
|
|
103
|
+
v-model="currentContent"
|
|
104
|
+
class="code-editor"
|
|
105
|
+
spellcheck="false"
|
|
106
|
+
@scroll="syncScroll"
|
|
107
|
+
@input="highlightCode"
|
|
108
|
+
@keydown.tab.prevent="handleTab"></textarea>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
<div v-if="errorMessage" class="error-container">
|
|
114
|
+
<div class="error-icon">
|
|
115
|
+
<svg
|
|
116
|
+
width="16"
|
|
117
|
+
height="16"
|
|
118
|
+
viewBox="0 0 24 24"
|
|
119
|
+
fill="none"
|
|
120
|
+
stroke="currentColor"
|
|
121
|
+
stroke-width="2">
|
|
122
|
+
<circle cx="12" cy="12" r="10" />
|
|
123
|
+
<line x1="15" y1="9" x2="9" y2="15" />
|
|
124
|
+
<line x1="9" y1="9" x2="15" y2="15" />
|
|
125
|
+
</svg>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="error-content">
|
|
128
|
+
<div class="error-title">JSON Syntax Error</div>
|
|
129
|
+
<div class="error-text">{{ errorMessage }}</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
59
132
|
</div>
|
|
133
|
+
</transition>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<!-- Section Divider - Show when both editors are closed -->
|
|
137
|
+
<div v-if="ui.profile.admin && !textEditorVisible && !currentProxyList" class="section-divider" />
|
|
60
138
|
|
|
61
|
-
|
|
139
|
+
<!-- Proxy Editor Section - Hidden when admin editor is open -->
|
|
140
|
+
<div class="proxy-editor-section" :class="{ 'landscape-hidden': textEditorVisible }">
|
|
141
|
+
<h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Proxy Editor</h5>
|
|
142
|
+
<div class="flex-responsive-wrap proxy-controls-row mb-1">
|
|
143
|
+
<div class="w-full lg:w-64 flex flex-shrink-0 dropdown-container z-dropdown">
|
|
144
|
+
<div class="relative flex-grow">
|
|
145
|
+
<Dropdown
|
|
146
|
+
class="bg-dark-500 border-2 border-dark-550 proxy-file-dropdown w-full"
|
|
147
|
+
:default="ui.profile.proxyList?.checkout || proxyLists[0]"
|
|
148
|
+
:onClick="loadProxies"
|
|
149
|
+
:options="proxyLists"
|
|
150
|
+
:allowDefault="false"
|
|
151
|
+
:includeAdjacentButtons="true"
|
|
152
|
+
rightAmount="right-1" />
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
<!-- Proxy save button moved here -->
|
|
156
|
+
<div
|
|
157
|
+
v-if="currentProxyList"
|
|
158
|
+
class="flex flex-wrap gap-responsive justify-center lg:justify-end editor-buttons-responsive">
|
|
159
|
+
<button class="btn-action flex-shrink-0" @click="saveProxies" title="Save Proxies">
|
|
160
|
+
<svg
|
|
161
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
162
|
+
width="16"
|
|
163
|
+
height="16"
|
|
164
|
+
viewBox="0 0 24 24"
|
|
165
|
+
fill="none"
|
|
166
|
+
stroke="currentColor"
|
|
167
|
+
stroke-width="2"
|
|
168
|
+
stroke-linecap="round"
|
|
169
|
+
stroke-linejoin="round">
|
|
170
|
+
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
|
|
171
|
+
<polyline points="17 21 17 13 7 13 7 21" />
|
|
172
|
+
<polyline points="7 3 7 8 15 8" />
|
|
173
|
+
</svg>
|
|
174
|
+
<span class="hidden sm:inline">Save Proxies</span>
|
|
175
|
+
</button>
|
|
176
|
+
<button class="btn-action flex-shrink-0" @click="closeProxyFile" title="Close File">
|
|
177
|
+
<svg
|
|
178
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
179
|
+
width="16"
|
|
180
|
+
height="16"
|
|
181
|
+
viewBox="0 0 24 24"
|
|
182
|
+
fill="none"
|
|
183
|
+
stroke="currentColor"
|
|
184
|
+
stroke-width="2"
|
|
185
|
+
stroke-linecap="round"
|
|
186
|
+
stroke-linejoin="round">
|
|
187
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
188
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
189
|
+
</svg>
|
|
190
|
+
<span class="hidden sm:inline">Close File</span>
|
|
191
|
+
</button>
|
|
192
|
+
</div>
|
|
62
193
|
</div>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
:allowDefault="false"
|
|
74
|
-
rightAmount="right-1"
|
|
75
|
-
/>
|
|
76
|
-
<button
|
|
77
|
-
v-if="currentProxyList"
|
|
78
|
-
class="bg-dark-500 border-2 border-dark-550 w-32 text-xs h-10 text-white rounded"
|
|
79
|
-
@click="saveProxies"
|
|
80
|
-
>
|
|
81
|
-
<i class="far fa-border-all"></i> Save Proxies
|
|
82
|
-
</button>
|
|
194
|
+
<!-- Textarea -->
|
|
195
|
+
<transition name="fade">
|
|
196
|
+
<div v-if="currentProxyList" class="relative my-3">
|
|
197
|
+
<div class="pb-4">
|
|
198
|
+
<div class="proxy-editor-container table-component">
|
|
199
|
+
<textarea v-model="proxyContent" class="proxy-editor" spellcheck="false"></textarea>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
</transition>
|
|
83
204
|
</div>
|
|
84
|
-
<!-- Textarea -->
|
|
85
|
-
<transition name="fade">
|
|
86
|
-
<div v-if="currentProxyList" class="max-h-64 lg:max-h-80 overflow-auto hidden-scrollbars z-0">
|
|
87
|
-
<CodeEditor
|
|
88
|
-
v-model="proxyContent"
|
|
89
|
-
width="100%"
|
|
90
|
-
spellcheck="false"
|
|
91
|
-
@change="format()"
|
|
92
|
-
:hide_header="true"
|
|
93
|
-
:language_selector="false"
|
|
94
|
-
:languages="[['text']]"
|
|
95
|
-
theme="dark"
|
|
96
|
-
class=""
|
|
97
|
-
></CodeEditor>
|
|
98
|
-
</div>
|
|
99
|
-
</transition>
|
|
100
205
|
</div>
|
|
101
|
-
<QuickSettings v-if="activeModal === 'quick-settings'" />
|
|
102
206
|
</div>
|
|
103
207
|
</template>
|
|
104
208
|
<script setup>
|
|
105
|
-
import { ref, computed, watch } from "vue";
|
|
209
|
+
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from "vue";
|
|
106
210
|
import { DownIcon, ReloadIcon, EditIcon } from "@/components/icons";
|
|
107
211
|
import { useUIStore } from "@/stores/ui";
|
|
108
|
-
import CodeEditor from "simple-code-editor";
|
|
109
|
-
|
|
110
212
|
import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
|
|
111
|
-
|
|
112
|
-
// needed, even though not used
|
|
113
|
-
import hljs from "highlight.js/lib/core";
|
|
114
|
-
import json from "highlight.js/lib/languages/json";
|
|
115
213
|
import { getProxyLists, getProxyFile } from "@/stores/requests";
|
|
116
|
-
|
|
117
|
-
const DEBUG = window.location.href.startsWith("http://localhost:5173");
|
|
118
|
-
|
|
119
|
-
hljs.registerLanguage("json", json);
|
|
214
|
+
import { DEBUG } from "@/utils/debug";
|
|
120
215
|
|
|
121
216
|
const loadFromApi = async (path) => {
|
|
122
217
|
const res = await fetch(path);
|
|
@@ -134,6 +229,10 @@ const currentProxyList = ref("");
|
|
|
134
229
|
const activeModal = computed(() => ui.activeModal);
|
|
135
230
|
const ui = useUIStore();
|
|
136
231
|
|
|
232
|
+
// References to editor elements
|
|
233
|
+
const codeEditor = ref(null);
|
|
234
|
+
const codeDisplay = ref(null);
|
|
235
|
+
|
|
137
236
|
let previous = {
|
|
138
237
|
proxyContent: { list: ui.profile.proxyList, content: "" },
|
|
139
238
|
currentContent: { file: "", content: "" }
|
|
@@ -155,30 +254,149 @@ const loadAvailableFiles = async () => (availableFiles.value = await loadFromApi
|
|
|
155
254
|
|
|
156
255
|
const isJsonFile = () => currentFile.value.endsWith(".json");
|
|
157
256
|
|
|
257
|
+
// Function to highlight code using Prism
|
|
258
|
+
const highlightCode = () => {
|
|
259
|
+
if (!codeDisplay.value || !codeEditor.value) return;
|
|
260
|
+
|
|
261
|
+
// Get the language based on file extension
|
|
262
|
+
let language = "javascript"; // Default language
|
|
263
|
+
|
|
264
|
+
if (currentFile.value) {
|
|
265
|
+
if (currentFile.value.endsWith(".json")) {
|
|
266
|
+
language = "json";
|
|
267
|
+
} else if (currentFile.value.endsWith(".js")) {
|
|
268
|
+
language = "javascript";
|
|
269
|
+
} else if (currentFile.value.endsWith(".txt") || currentFile.value.endsWith(".csv")) {
|
|
270
|
+
language = "text";
|
|
271
|
+
// Plain text doesn't need highlighting
|
|
272
|
+
codeDisplay.value.textContent = currentContent.value || "";
|
|
273
|
+
codeDisplay.value.className = "language-text code-highlight";
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Ensure Prism is available
|
|
279
|
+
if (typeof Prism === "undefined") {
|
|
280
|
+
console.error("Prism is not loaded");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Use requestAnimationFrame for smoother updates
|
|
285
|
+
requestAnimationFrame(() => {
|
|
286
|
+
try {
|
|
287
|
+
// Update the pre element with highlighted HTML
|
|
288
|
+
const highlighted = Prism.highlight(currentContent.value || "", Prism.languages[language], language);
|
|
289
|
+
codeDisplay.value.innerHTML = highlighted;
|
|
290
|
+
codeDisplay.value.className = `language-${language} code-highlight`;
|
|
291
|
+
} catch (e) {
|
|
292
|
+
console.error("Highlight error:", e);
|
|
293
|
+
// Fallback to plain text if highlighting fails
|
|
294
|
+
codeDisplay.value.textContent = currentContent.value || "";
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Ensure scroll positions are synced after highlighting
|
|
298
|
+
syncScroll();
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// Function to sync scrolling between textarea and highlighted code
|
|
303
|
+
const syncScroll = () => {
|
|
304
|
+
if (!codeDisplay.value || !codeEditor.value) return;
|
|
305
|
+
|
|
306
|
+
// Synchronize scrolling between the textarea and the highlighted code
|
|
307
|
+
requestAnimationFrame(() => {
|
|
308
|
+
codeDisplay.value.scrollTop = codeEditor.value.scrollTop;
|
|
309
|
+
codeDisplay.value.scrollLeft = codeEditor.value.scrollLeft;
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// Function to handle tab key press in the editor
|
|
314
|
+
const handleTab = (e) => {
|
|
315
|
+
const textarea = codeEditor.value;
|
|
316
|
+
const start = textarea.selectionStart;
|
|
317
|
+
const end = textarea.selectionEnd;
|
|
318
|
+
|
|
319
|
+
// Insert 4 spaces at cursor position
|
|
320
|
+
const spaces = " ";
|
|
321
|
+
currentContent.value = currentContent.value.substring(0, start) + spaces + currentContent.value.substring(end);
|
|
322
|
+
|
|
323
|
+
// Move cursor position after the inserted tab
|
|
324
|
+
nextTick(() => {
|
|
325
|
+
textarea.selectionStart = textarea.selectionEnd = start + spaces.length;
|
|
326
|
+
highlightCode();
|
|
327
|
+
});
|
|
328
|
+
};
|
|
329
|
+
|
|
158
330
|
const format = () => {
|
|
159
331
|
try {
|
|
160
332
|
if (!isJsonFile()) return;
|
|
161
333
|
|
|
162
334
|
const formatted = JSON.stringify(JSON.parse(currentContent.value), null, 4);
|
|
163
335
|
currentContent.value = formatted;
|
|
336
|
+
|
|
337
|
+
// Apply syntax highlighting after formatting
|
|
338
|
+
nextTick(() => {
|
|
339
|
+
highlightCode();
|
|
340
|
+
});
|
|
164
341
|
} catch (e) {
|
|
165
|
-
ui.logger.Error("Could not
|
|
342
|
+
ui.logger.Error("Could not format JSON", e);
|
|
166
343
|
}
|
|
167
344
|
};
|
|
168
345
|
|
|
346
|
+
// Watch for content changes to apply syntax highlighting
|
|
347
|
+
watch(currentContent, () => {
|
|
348
|
+
nextTick(() => {
|
|
349
|
+
highlightCode();
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
169
353
|
const loadFile = async (f) => {
|
|
170
354
|
currentFile.value = f;
|
|
171
355
|
if (DEBUG) {
|
|
172
356
|
textEditorVisible.value = true;
|
|
173
357
|
currentProxyList.value = "";
|
|
174
|
-
|
|
358
|
+
currentContent.value = new Array(100).fill(0, 0, 100).join("\n");
|
|
359
|
+
|
|
360
|
+
// Update pre element class based on file type
|
|
361
|
+
if (codeDisplay.value) {
|
|
362
|
+
if (f.endsWith(".json")) {
|
|
363
|
+
codeDisplay.value.className = "language-json";
|
|
364
|
+
} else if (f.endsWith(".js")) {
|
|
365
|
+
codeDisplay.value.className = "language-javascript";
|
|
366
|
+
} else {
|
|
367
|
+
codeDisplay.value.className = "language-text";
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Apply syntax highlighting after content is set
|
|
372
|
+
nextTick(() => {
|
|
373
|
+
highlightCode();
|
|
374
|
+
});
|
|
375
|
+
return;
|
|
175
376
|
}
|
|
377
|
+
|
|
176
378
|
const res = await loadFromApi("/api/json-file?file=" + currentFile.value);
|
|
177
379
|
const text = atob(res.content);
|
|
178
380
|
textEditorVisible.value = true;
|
|
179
381
|
currentProxyList.value = "";
|
|
180
382
|
currentContent.value = text;
|
|
181
383
|
previous.currentContent = { file: currentFile.value, content: text };
|
|
384
|
+
|
|
385
|
+
// Update pre element class based on file type
|
|
386
|
+
if (codeDisplay.value) {
|
|
387
|
+
if (f.endsWith(".json")) {
|
|
388
|
+
codeDisplay.value.className = "language-json";
|
|
389
|
+
} else if (f.endsWith(".js")) {
|
|
390
|
+
codeDisplay.value.className = "language-javascript";
|
|
391
|
+
} else {
|
|
392
|
+
codeDisplay.value.className = "language-text";
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Apply syntax highlighting after content is loaded
|
|
397
|
+
nextTick(() => {
|
|
398
|
+
highlightCode();
|
|
399
|
+
});
|
|
182
400
|
};
|
|
183
401
|
|
|
184
402
|
const saveDataToAPI = async (data, endpoint, msg, json = true) => {
|
|
@@ -217,7 +435,10 @@ const saveFile = async () => {
|
|
|
217
435
|
)
|
|
218
436
|
return ui.logger.Info("Content did not change");
|
|
219
437
|
saveDataToAPI(btoa(currentContent.value), "/api/json-file?file=" + currentFile.value, "Successfully saved file");
|
|
220
|
-
previous.currentContent = {
|
|
438
|
+
previous.currentContent = {
|
|
439
|
+
file: currentFile.value,
|
|
440
|
+
content: btoa(currentContent.value)
|
|
441
|
+
};
|
|
221
442
|
};
|
|
222
443
|
|
|
223
444
|
const saveAll = async () => {
|
|
@@ -226,13 +447,28 @@ const saveAll = async () => {
|
|
|
226
447
|
await saveQuickConfig();
|
|
227
448
|
};
|
|
228
449
|
|
|
450
|
+
const closeFile = () => {
|
|
451
|
+
currentFile.value = "";
|
|
452
|
+
currentContent.value = "";
|
|
453
|
+
textEditorVisible.value = false;
|
|
454
|
+
ui.logger.Info("File closed");
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const closeProxyFile = () => {
|
|
458
|
+
currentProxyList.value = "";
|
|
459
|
+
proxyContent.value = "";
|
|
460
|
+
ui.logger.Info("Proxy file closed");
|
|
461
|
+
};
|
|
462
|
+
|
|
229
463
|
const loadProxies = async (list) => {
|
|
230
464
|
try {
|
|
231
465
|
if (DEBUG) {
|
|
232
466
|
currentProxyList.value = list;
|
|
233
467
|
textEditorVisible.value = false;
|
|
234
|
-
|
|
468
|
+
proxyContent.value = new Array(100).fill(0, 0, 100).join("\n");
|
|
469
|
+
return;
|
|
235
470
|
}
|
|
471
|
+
|
|
236
472
|
ui.logger.Info("Loading proxies: " + list);
|
|
237
473
|
currentProxyList.value = list;
|
|
238
474
|
const file = await getProxyFile(list);
|
|
@@ -265,10 +501,469 @@ const loadProxyLists = async () => {
|
|
|
265
501
|
else ui.showError("Could not load proxylists");
|
|
266
502
|
};
|
|
267
503
|
|
|
504
|
+
// Initialize syntax highlighting
|
|
505
|
+
onMounted(() => {
|
|
506
|
+
// Apply highlighting when the component is mounted
|
|
507
|
+
nextTick(() => {
|
|
508
|
+
highlightCode();
|
|
509
|
+
|
|
510
|
+
// Ensure scroll synchronization on initial load
|
|
511
|
+
if (codeEditor.value && codeDisplay.value) {
|
|
512
|
+
syncScroll();
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
// iOS-specific editor fixes with cursor tracking
|
|
517
|
+
if (
|
|
518
|
+
/iPad|iPhone|iPod/.test(navigator.platform) ||
|
|
519
|
+
(navigator.maxTouchPoints && navigator.maxTouchPoints > 2 && /MacIntel/.test(navigator.platform))
|
|
520
|
+
) {
|
|
521
|
+
const trackCursor = (editor) => {
|
|
522
|
+
const scrollToCursor = () => {
|
|
523
|
+
setTimeout(() => {
|
|
524
|
+
const container = editor.closest(".editor-container") || editor.closest(".proxy-editor-container");
|
|
525
|
+
if (container) {
|
|
526
|
+
// Get cursor position and scroll to it
|
|
527
|
+
const lines = editor.value.substring(0, editor.selectionStart).split("\n");
|
|
528
|
+
const lineHeight = 24; // Approximate line height
|
|
529
|
+
const cursorY = lines.length * lineHeight;
|
|
530
|
+
const containerHeight = container.clientHeight;
|
|
531
|
+
|
|
532
|
+
// Scroll to keep cursor in view
|
|
533
|
+
if (cursorY > container.scrollTop + containerHeight - 60) {
|
|
534
|
+
container.scrollTop = cursorY - containerHeight + 60;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}, 100);
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
editor.addEventListener("focus", scrollToCursor);
|
|
541
|
+
editor.addEventListener("input", scrollToCursor);
|
|
542
|
+
editor.addEventListener("click", scrollToCursor);
|
|
543
|
+
editor.addEventListener("keyup", scrollToCursor);
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
nextTick(() => {
|
|
547
|
+
if (codeEditor.value) {
|
|
548
|
+
trackCursor(codeEditor.value);
|
|
549
|
+
}
|
|
550
|
+
const proxyEditor = document.querySelector(".proxy-editor");
|
|
551
|
+
if (proxyEditor) {
|
|
552
|
+
trackCursor(proxyEditor);
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Watch for editor visibility changes
|
|
558
|
+
watch(textEditorVisible, (newValue) => {
|
|
559
|
+
if (newValue) {
|
|
560
|
+
nextTick(() => {
|
|
561
|
+
highlightCode();
|
|
562
|
+
|
|
563
|
+
// Focus the editor when it becomes visible
|
|
564
|
+
if (codeEditor.value) {
|
|
565
|
+
codeEditor.value.focus();
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// No cleanup needed - global iOS handling takes care of everything
|
|
573
|
+
|
|
268
574
|
if (ui.profile.admin && !DEBUG) loadAvailableFiles();
|
|
269
575
|
loadProxyLists();
|
|
270
576
|
</script>
|
|
271
577
|
<style lang="scss" scoped>
|
|
578
|
+
/* ==========================================================================
|
|
579
|
+
Z-INDEX MANAGEMENT
|
|
580
|
+
========================================================================== */
|
|
581
|
+
|
|
582
|
+
.z-dropdown-high {
|
|
583
|
+
position: relative;
|
|
584
|
+
z-index: 200;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.z-dropdown-high .dropdown-menu,
|
|
588
|
+
.z-dropdown-high .option-list {
|
|
589
|
+
z-index: 250;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
.z-dropdown {
|
|
593
|
+
position: relative;
|
|
594
|
+
z-index: 100;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.z-dropdown .dropdown-menu,
|
|
598
|
+
.z-dropdown .option-list {
|
|
599
|
+
z-index: 150;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/* ==========================================================================
|
|
603
|
+
CARD CONTAINER RESPONSIVENESS
|
|
604
|
+
Component-scoped definition (not global utility)
|
|
605
|
+
========================================================================== */
|
|
606
|
+
|
|
607
|
+
.card-dark {
|
|
608
|
+
max-height: calc(100vh - 100px) !important;
|
|
609
|
+
overflow-y: auto !important;
|
|
610
|
+
-webkit-overflow-scrolling: touch !important;
|
|
611
|
+
margin-bottom: 0.5rem !important;
|
|
612
|
+
padding-bottom: 0.5rem !important;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/* ==========================================================================
|
|
616
|
+
ADMIN EDITOR SECTION CONDITIONAL VISIBILITY
|
|
617
|
+
========================================================================== */
|
|
618
|
+
|
|
619
|
+
.admin-editor-section {
|
|
620
|
+
/* Default: always visible */
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/* Hide admin editor when proxy editor is open - ALL SCREEN SIZES */
|
|
624
|
+
.admin-editor-section.landscape-hidden {
|
|
625
|
+
display: none !important;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/* ==========================================================================
|
|
629
|
+
PROXY EDITOR SECTION CONDITIONAL VISIBILITY
|
|
630
|
+
========================================================================== */
|
|
631
|
+
|
|
632
|
+
.proxy-editor-section {
|
|
633
|
+
/* Default: always visible */
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/* Hide proxy editor when admin editor is open - ALL SCREEN SIZES */
|
|
637
|
+
.proxy-editor-section.landscape-hidden {
|
|
638
|
+
display: none !important;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/* Ensure card has proper bottom margin when sections are hidden */
|
|
642
|
+
.proxy-editor-section.landscape-hidden ~ .card-dark,
|
|
643
|
+
.admin-editor-section.landscape-hidden ~ .card-dark {
|
|
644
|
+
margin-bottom: 1rem !important;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/* ==========================================================================
|
|
648
|
+
SECTION HEADERS
|
|
649
|
+
========================================================================== */
|
|
650
|
+
|
|
651
|
+
.admin-editor-section h5,
|
|
652
|
+
.proxy-editor-section h5 {
|
|
653
|
+
/* Remove the gradient underline styling */
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/* ==========================================================================
|
|
657
|
+
ADMIN FILE DROPDOWN STYLING
|
|
658
|
+
========================================================================== */
|
|
659
|
+
|
|
660
|
+
.admin-file-dropdown {
|
|
661
|
+
height: 2.5rem !important;
|
|
662
|
+
border-top-right-radius: 0 !important;
|
|
663
|
+
border-bottom-right-radius: 0 !important;
|
|
664
|
+
border-top-left-radius: 0.5rem !important;
|
|
665
|
+
border-bottom-left-radius: 0.5rem !important;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
.proxy-file-dropdown {
|
|
669
|
+
height: 2.5rem !important;
|
|
670
|
+
border-radius: 0.5rem !important;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.refresh-button {
|
|
674
|
+
height: 2.5rem !important;
|
|
675
|
+
transition: all 0.2s ease;
|
|
676
|
+
|
|
677
|
+
&:hover {
|
|
678
|
+
.refresh-icon {
|
|
679
|
+
transform: rotate(180deg);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
.refresh-icon {
|
|
685
|
+
transition: transform 0.5s ease;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/* ==========================================================================
|
|
689
|
+
EDITOR CONTAINERS
|
|
690
|
+
========================================================================== */
|
|
691
|
+
|
|
692
|
+
.editor-container,
|
|
693
|
+
.proxy-editor-container {
|
|
694
|
+
position: relative;
|
|
695
|
+
overflow: hidden;
|
|
696
|
+
height: 400px;
|
|
697
|
+
max-height: 60vh;
|
|
698
|
+
border-radius: 8px;
|
|
699
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
700
|
+
background-color: oklch(0.19 0 0);
|
|
701
|
+
transition: height 0.3s ease;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.proxy-editor-container {
|
|
705
|
+
/* Ensure proxy editor takes full container space */
|
|
706
|
+
display: flex;
|
|
707
|
+
flex-direction: column;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.proxy-editor-container .pb-4 {
|
|
711
|
+
/* Remove bottom padding to maximize space */
|
|
712
|
+
padding-bottom: 0 !important;
|
|
713
|
+
flex: 1;
|
|
714
|
+
display: flex;
|
|
715
|
+
flex-direction: column;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
.proxy-editor-container .table-component {
|
|
719
|
+
/* Make proxy editor container take full height */
|
|
720
|
+
flex: 1;
|
|
721
|
+
display: flex;
|
|
722
|
+
flex-direction: column;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.editor-wrapper {
|
|
726
|
+
position: relative;
|
|
727
|
+
width: 100%;
|
|
728
|
+
height: 100%;
|
|
729
|
+
overflow: hidden;
|
|
730
|
+
border-radius: 8px;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/* ==========================================================================
|
|
734
|
+
EDITOR TEXTAREAS
|
|
735
|
+
========================================================================== */
|
|
736
|
+
|
|
737
|
+
.code-editor,
|
|
738
|
+
.proxy-editor {
|
|
739
|
+
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
740
|
+
font-size: 14px;
|
|
741
|
+
line-height: 1.6;
|
|
742
|
+
tab-size: 4;
|
|
743
|
+
background-color: transparent;
|
|
744
|
+
border: none;
|
|
745
|
+
outline: none;
|
|
746
|
+
resize: none;
|
|
747
|
+
width: 100%;
|
|
748
|
+
height: 100%;
|
|
749
|
+
overflow: auto;
|
|
750
|
+
-webkit-overflow-scrolling: touch;
|
|
751
|
+
padding: 12px;
|
|
752
|
+
margin: 0;
|
|
753
|
+
box-sizing: border-box;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
.code-editor {
|
|
757
|
+
/* Make textarea text transparent so syntax highlighting shows through */
|
|
758
|
+
color: transparent !important;
|
|
759
|
+
z-index: 2;
|
|
760
|
+
position: relative;
|
|
761
|
+
background-color: transparent;
|
|
762
|
+
caret-color: #ffffff; /* Keep cursor visible */
|
|
763
|
+
|
|
764
|
+
/* Selection styling */
|
|
765
|
+
&::selection {
|
|
766
|
+
background-color: rgba(255, 255, 255, 0.2);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.proxy-editor {
|
|
771
|
+
@apply w-full h-full resize-none focus:outline-none;
|
|
772
|
+
background-color: transparent;
|
|
773
|
+
color: oklch(0.90 0 0); /* Keep normal text color for proxy editor */
|
|
774
|
+
/* Ensure proxy editor takes full height */
|
|
775
|
+
flex: 1;
|
|
776
|
+
min-height: 100%;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/* ==========================================================================
|
|
780
|
+
CODE HIGHLIGHTING
|
|
781
|
+
========================================================================== */
|
|
782
|
+
|
|
783
|
+
.code-highlight {
|
|
784
|
+
font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
|
|
785
|
+
font-size: 14px;
|
|
786
|
+
line-height: 1.6;
|
|
787
|
+
tab-size: 4;
|
|
788
|
+
/* Remove transparent color - let syntax highlighting show */
|
|
789
|
+
color: #f8f8f2 !important;
|
|
790
|
+
background: transparent;
|
|
791
|
+
border: none;
|
|
792
|
+
outline: none;
|
|
793
|
+
resize: none;
|
|
794
|
+
width: 100%;
|
|
795
|
+
height: 100%;
|
|
796
|
+
overflow: hidden;
|
|
797
|
+
white-space: pre;
|
|
798
|
+
pointer-events: none;
|
|
799
|
+
z-index: 1;
|
|
800
|
+
position: absolute;
|
|
801
|
+
top: 0;
|
|
802
|
+
left: 0;
|
|
803
|
+
padding: 12px;
|
|
804
|
+
margin: 0;
|
|
805
|
+
box-sizing: border-box;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/* ==========================================================================
|
|
809
|
+
PRISM.JS SYNTAX HIGHLIGHTING THEME
|
|
810
|
+
========================================================================== */
|
|
811
|
+
|
|
812
|
+
code[class*="language-"],
|
|
813
|
+
pre[class*="language-"] {
|
|
814
|
+
color: #f8f8f2;
|
|
815
|
+
background: none;
|
|
816
|
+
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
|
|
817
|
+
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
|
818
|
+
text-align: left;
|
|
819
|
+
white-space: pre;
|
|
820
|
+
word-spacing: normal;
|
|
821
|
+
word-break: normal;
|
|
822
|
+
word-wrap: normal;
|
|
823
|
+
line-height: 1.5;
|
|
824
|
+
tab-size: 4;
|
|
825
|
+
hyphens: none;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
pre[class*="language-"] {
|
|
829
|
+
padding: 12px;
|
|
830
|
+
margin: 0;
|
|
831
|
+
overflow: auto;
|
|
832
|
+
border-radius: 4px;
|
|
833
|
+
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
|
834
|
+
font-size: 14px;
|
|
835
|
+
line-height: 1.5;
|
|
836
|
+
tab-size: 4;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
:not(pre) > code[class*="language-"],
|
|
840
|
+
pre[class*="language-"] {
|
|
841
|
+
background: oklch(0.19 0 0);
|
|
842
|
+
white-space: pre;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
:not(pre) > code[class*="language-"] {
|
|
846
|
+
padding: 0.1em;
|
|
847
|
+
border-radius: 0.3em;
|
|
848
|
+
white-space: normal;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
.token.comment,
|
|
852
|
+
.token.prolog,
|
|
853
|
+
.token.doctype,
|
|
854
|
+
.token.cdata {
|
|
855
|
+
color: #676f7d;
|
|
856
|
+
font-style: italic;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
.token.punctuation {
|
|
860
|
+
color: #a9b7c6;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
.namespace {
|
|
864
|
+
opacity: 0.8;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
.token.property,
|
|
868
|
+
.token.tag,
|
|
869
|
+
.token.constant,
|
|
870
|
+
.token.symbol,
|
|
871
|
+
.token.deleted {
|
|
872
|
+
color: #e06c75;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
.token.boolean,
|
|
876
|
+
.token.number {
|
|
877
|
+
color: #c792ea;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
.token.selector,
|
|
881
|
+
.token.attr-name,
|
|
882
|
+
.token.string,
|
|
883
|
+
.token.char,
|
|
884
|
+
.token.builtin,
|
|
885
|
+
.token.inserted {
|
|
886
|
+
color: #98c379;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
.token.operator,
|
|
890
|
+
.token.entity,
|
|
891
|
+
.token.url,
|
|
892
|
+
.language-css .token.string,
|
|
893
|
+
.style .token.string {
|
|
894
|
+
color: #89ddff;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.token.atrule,
|
|
898
|
+
.token.attr-value,
|
|
899
|
+
.token.keyword {
|
|
900
|
+
color: #61afef;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
.token.function,
|
|
904
|
+
.token.class-name {
|
|
905
|
+
color: #ffcb6b;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
.token.regex,
|
|
909
|
+
.token.important,
|
|
910
|
+
.token.variable {
|
|
911
|
+
color: #c5e478;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.token.important,
|
|
915
|
+
.token.bold {
|
|
916
|
+
font-weight: bold;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.token.italic {
|
|
920
|
+
font-style: italic;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
.token.entity {
|
|
924
|
+
cursor: help;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
.editor-container:hover {
|
|
928
|
+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
|
|
929
|
+
transition: box-shadow 0.3s ease;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/* ==========================================================================
|
|
933
|
+
ERROR MESSAGES
|
|
934
|
+
========================================================================== */
|
|
935
|
+
|
|
936
|
+
.error-container {
|
|
937
|
+
@apply flex items-start gap-3 p-4 bg-red-500/10 border border-red-500/20 rounded-lg mt-4 mb-4;
|
|
938
|
+
|
|
939
|
+
/* Prevent overflow in landscape mode */
|
|
940
|
+
max-width: 100%;
|
|
941
|
+
word-wrap: break-word;
|
|
942
|
+
overflow-wrap: break-word;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
.error-icon {
|
|
946
|
+
@apply flex-shrink-0 text-red-400;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
.error-content {
|
|
950
|
+
@apply flex-1;
|
|
951
|
+
min-width: 0; /* Allow text to shrink */
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.error-title {
|
|
955
|
+
@apply text-red-400 font-medium text-sm mb-1;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.error-text {
|
|
959
|
+
@apply text-red-300 text-xs;
|
|
960
|
+
word-break: break-word;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/* ==========================================================================
|
|
964
|
+
CONSOLE STYLES
|
|
965
|
+
========================================================================== */
|
|
966
|
+
|
|
272
967
|
.console {
|
|
273
968
|
@apply bg-dark-400 p-7 rounded relative border-dark-550 border-2;
|
|
274
969
|
|
|
@@ -278,41 +973,399 @@ loadProxyLists();
|
|
|
278
973
|
height: calc(100vh - 450px);
|
|
279
974
|
@apply w-full focus:outline-none text-xs text-white;
|
|
280
975
|
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/* ==========================================================================
|
|
979
|
+
SECTION DIVIDER
|
|
980
|
+
========================================================================== */
|
|
281
981
|
|
|
282
|
-
|
|
982
|
+
.section-divider {
|
|
983
|
+
margin: 24px 0; /* Balanced margin for better centering */
|
|
984
|
+
height: 1px;
|
|
985
|
+
width: 100%;
|
|
986
|
+
position: relative;
|
|
283
987
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// background: radial-gradient(rgba(96, 66, 255, 0.6), rgba(255, 255, 255, 0));
|
|
291
|
-
// }
|
|
988
|
+
/* Add subtle gradient effect for better visual separation */
|
|
989
|
+
background: linear-gradient(90deg, transparent 0%, oklch(0.26 0 0) 20%, oklch(0.26 0 0) 80%, transparent 100%);
|
|
990
|
+
border: none;
|
|
991
|
+
|
|
992
|
+
/* Add a subtle glow effect */
|
|
993
|
+
box-shadow: 0 0 8px rgba(61, 62, 68, 0.3);
|
|
292
994
|
}
|
|
293
995
|
|
|
294
|
-
|
|
295
|
-
|
|
996
|
+
/* ==========================================================================
|
|
997
|
+
RESPONSIVE LAYOUT UTILITIES
|
|
998
|
+
========================================================================== */
|
|
999
|
+
|
|
1000
|
+
.flex-responsive-wrap {
|
|
1001
|
+
@apply flex flex-wrap items-center gap-4;
|
|
296
1002
|
}
|
|
297
1003
|
|
|
298
|
-
|
|
299
|
-
|
|
1004
|
+
/* ==========================================================================
|
|
1005
|
+
MOBILE RESPONSIVE STYLES (max-width: 767px)
|
|
1006
|
+
========================================================================== */
|
|
1007
|
+
|
|
1008
|
+
@media (max-width: 767px) {
|
|
1009
|
+
/* Card container - increased height to use more available space */
|
|
1010
|
+
.card-dark {
|
|
1011
|
+
max-height: calc(100vh - 100px) !important; /* Increased from 120px */
|
|
1012
|
+
overflow-y: auto !important;
|
|
1013
|
+
-webkit-overflow-scrolling: touch !important;
|
|
1014
|
+
margin-bottom: 0.5rem !important; /* Reduced from 1rem */
|
|
1015
|
+
/* Reduced bottom padding to minimize empty space */
|
|
1016
|
+
padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
/* Layout adjustments - almost no gap between dropdown and buttons */
|
|
1020
|
+
.flex-responsive-wrap {
|
|
1021
|
+
@apply flex-col items-stretch !important;
|
|
1022
|
+
gap: 0px !important; /* Reduced from 2px to eliminate space between dropdown and buttons */
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/* Button container - even spacing across full width */
|
|
1026
|
+
.flex-responsive-wrap > div:last-child {
|
|
1027
|
+
@apply flex justify-center !important;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/* Smaller buttons on mobile */
|
|
1031
|
+
.btn-action {
|
|
1032
|
+
height: 32px !important;
|
|
1033
|
+
min-height: 32px !important;
|
|
1034
|
+
padding: 0 8px !important;
|
|
1035
|
+
font-size: 12px !important;
|
|
1036
|
+
|
|
1037
|
+
svg {
|
|
1038
|
+
width: 14px !important;
|
|
1039
|
+
height: 14px !important;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/* Editor container heights - reduced for better mobile experience */
|
|
1044
|
+
.editor-container,
|
|
1045
|
+
.proxy-editor-container {
|
|
1046
|
+
height: 200px !important; /* Reduced from 280px for better mobile experience */
|
|
1047
|
+
max-height: 30vh !important; /* Reduced from 35vh */
|
|
1048
|
+
min-height: 180px !important; /* Reduced from 220px */
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/* Reduce editor height when JSON error is showing in portrait */
|
|
1052
|
+
.editor-container.has-error {
|
|
1053
|
+
height: 160px !important; /* Reduced to make room for error message */
|
|
1054
|
+
max-height: 25vh !important;
|
|
1055
|
+
min-height: 140px !important;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/* Error message spacing on mobile */
|
|
1059
|
+
.error-container {
|
|
1060
|
+
margin: 8px 0 !important;
|
|
1061
|
+
padding: 8px !important;
|
|
1062
|
+
font-size: 11px !important;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.error-title {
|
|
1066
|
+
font-size: 11px !important;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.error-text {
|
|
1070
|
+
font-size: 10px !important;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
/* Compact editor controls spacing - no margins */
|
|
1074
|
+
.editor-controls-row,
|
|
1075
|
+
.proxy-controls-row {
|
|
1076
|
+
margin-bottom: 0px !important; /* Eliminated margin completely */
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/* Compact editor containers - reduced margins for more space */
|
|
1080
|
+
.my-3 {
|
|
1081
|
+
margin: 6px 0 !important; /* Reduced margin between editor and controls */
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.pb-4 {
|
|
1085
|
+
padding-bottom: 4px !important; /* Reduced padding */
|
|
1086
|
+
}
|
|
300
1087
|
}
|
|
301
1088
|
|
|
302
|
-
|
|
303
|
-
|
|
1089
|
+
/* ==========================================================================
|
|
1090
|
+
TABLET RESPONSIVE STYLES (min-width: 768px)
|
|
1091
|
+
========================================================================== */
|
|
1092
|
+
|
|
1093
|
+
@media (min-width: 768px) {
|
|
1094
|
+
.flex-responsive-wrap {
|
|
1095
|
+
@apply flex-row justify-between items-center !important;
|
|
1096
|
+
}
|
|
304
1097
|
}
|
|
305
1098
|
|
|
306
|
-
|
|
307
|
-
|
|
1099
|
+
/* ==========================================================================
|
|
1100
|
+
DESKTOP RESPONSIVE STYLES (min-width: 1024px)
|
|
1101
|
+
========================================================================== */
|
|
1102
|
+
|
|
1103
|
+
@media (min-width: 1024px) {
|
|
1104
|
+
.editor-container,
|
|
1105
|
+
.proxy-editor-container {
|
|
1106
|
+
max-height: 60vh;
|
|
1107
|
+
}
|
|
308
1108
|
}
|
|
309
1109
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
1110
|
+
/* ==========================================================================
|
|
1111
|
+
LARGE DESKTOP RESPONSIVE STYLES (min-width: 1280px)
|
|
1112
|
+
========================================================================== */
|
|
1113
|
+
|
|
1114
|
+
@media (min-width: 1280px) {
|
|
1115
|
+
.editor-container,
|
|
1116
|
+
.proxy-editor-container {
|
|
1117
|
+
max-height: 70vh;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
/* ==========================================================================
|
|
1122
|
+
MOBILE LANDSCAPE MODE (max-height: 500px + landscape)
|
|
1123
|
+
========================================================================== */
|
|
1124
|
+
|
|
1125
|
+
@media (max-height: 500px) and (orientation: landscape) and (min-width: 568px) {
|
|
1126
|
+
/* Make card fit in landscape mode with reduced bottom spacing */
|
|
1127
|
+
.card-dark {
|
|
1128
|
+
max-height: calc(100vh - 80px) !important; /* Increased from 60px to 80px */
|
|
1129
|
+
overflow-y: auto !important;
|
|
1130
|
+
-webkit-overflow-scrolling: touch !important;
|
|
1131
|
+
margin-bottom: 0.5rem !important; /* Reduced from 1rem */
|
|
1132
|
+
padding: 8px !important;
|
|
1133
|
+
/* Reduced bottom padding to minimize empty space */
|
|
1134
|
+
padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/* Truncate card cleanly when admin editor is open */
|
|
1138
|
+
.admin-editor-section:not(.landscape-hidden) + .section-divider + .proxy-editor-section.landscape-hidden {
|
|
1139
|
+
display: none !important;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/* Ensure proxy editor takes full space when visible */
|
|
1143
|
+
.proxy-editor-container {
|
|
1144
|
+
height: 130px !important;
|
|
1145
|
+
max-height: 130px !important;
|
|
1146
|
+
min-height: 100px !important;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
.proxy-editor {
|
|
1150
|
+
height: 100% !important;
|
|
1151
|
+
min-height: 100% !important;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
/* Compact headings */
|
|
1155
|
+
h4 {
|
|
1156
|
+
font-size: 16px !important;
|
|
1157
|
+
margin-bottom: 6px !important;
|
|
1158
|
+
padding-top: 1rem !important;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
h5 {
|
|
1162
|
+
font-size: 14px !important;
|
|
1163
|
+
margin-bottom: 4px !important;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
/* Section divider */
|
|
1167
|
+
.section-divider {
|
|
1168
|
+
margin: 6px 0 !important;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/* Editor controls layout */
|
|
1172
|
+
.editor-controls-row,
|
|
1173
|
+
.proxy-controls-row {
|
|
1174
|
+
gap: 6px !important;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/* Compact button styling */
|
|
1178
|
+
.btn-action {
|
|
1179
|
+
min-height: 28px !important;
|
|
1180
|
+
height: 28px !important;
|
|
1181
|
+
padding: 0 6px !important;
|
|
1182
|
+
font-size: 11px !important;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/* Hide button text to save space */
|
|
1186
|
+
.btn-action span {
|
|
1187
|
+
display: none !important;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
/* Compact editor containers - reduced margins for more space */
|
|
1191
|
+
.my-3 {
|
|
1192
|
+
margin: 4px 0 !important; /* Reduced from 6px */
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.pb-4 {
|
|
1196
|
+
padding-bottom: 2px !important; /* Reduced from 4px */
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
/* Editor container heights - increased to use more available space */
|
|
1200
|
+
.editor-container,
|
|
1201
|
+
.proxy-editor-container {
|
|
1202
|
+
height: 180px !important; /* Increased from 130px */
|
|
1203
|
+
max-height: 180px !important;
|
|
1204
|
+
min-height: 150px !important; /* Increased from 100px */
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/* Reduce editor height when JSON error is showing */
|
|
1208
|
+
.editor-container.has-error {
|
|
1209
|
+
height: 120px !important; /* Reduced to make room for error message */
|
|
1210
|
+
max-height: 120px !important;
|
|
1211
|
+
min-height: 100px !important;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
/* Ensure proxy editor takes full space when visible - increased height */
|
|
1215
|
+
.proxy-editor-container {
|
|
1216
|
+
height: 180px !important; /* Increased from 130px */
|
|
1217
|
+
max-height: 180px !important;
|
|
1218
|
+
min-height: 150px !important;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/* Editor textarea heights - ensure syntax highlighting works */
|
|
1222
|
+
.code-editor,
|
|
1223
|
+
.proxy-editor {
|
|
1224
|
+
font-size: 11px !important;
|
|
1225
|
+
line-height: 1.4 !important;
|
|
1226
|
+
padding: 6px !important;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
/* Syntax highlighting in landscape mode */
|
|
1230
|
+
.code-highlight {
|
|
1231
|
+
font-size: 11px !important;
|
|
1232
|
+
line-height: 1.4 !important;
|
|
1233
|
+
padding: 6px !important;
|
|
1234
|
+
/* Ensure syntax highlighting is visible in landscape */
|
|
1235
|
+
color: #f8f8f2 !important;
|
|
1236
|
+
opacity: 1 !important;
|
|
1237
|
+
display: block !important;
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
/* Compact error messages */
|
|
1241
|
+
.error-container {
|
|
1242
|
+
margin: 2px 0 !important; /* Reduced from 4px */
|
|
1243
|
+
padding: 4px 6px !important; /* More compact padding */
|
|
1244
|
+
font-size: 9px !important; /* Reduced from 10px */
|
|
1245
|
+
border-radius: 4px !important; /* Smaller border radius */
|
|
1246
|
+
gap: 6px !important; /* Reduced gap */
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
.error-icon {
|
|
1250
|
+
width: 12px !important;
|
|
1251
|
+
height: 12px !important;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
.error-icon svg {
|
|
1255
|
+
width: 12px !important;
|
|
1256
|
+
height: 12px !important;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
.error-title {
|
|
1260
|
+
font-size: 9px !important; /* Reduced from 10px */
|
|
1261
|
+
margin-bottom: 2px !important;
|
|
1262
|
+
font-weight: 500 !important;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
.error-text {
|
|
1266
|
+
font-size: 8px !important; /* Reduced from 9px */
|
|
1267
|
+
line-height: 1.2 !important;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
/* ==========================================================================
|
|
1272
|
+
VERY SHORT LANDSCAPE SCREENS (max-height: 400px + landscape)
|
|
1273
|
+
========================================================================== */
|
|
1274
|
+
|
|
1275
|
+
@media (max-height: 400px) and (orientation: landscape) {
|
|
1276
|
+
.card-dark {
|
|
1277
|
+
max-height: calc(100vh - 70px) !important; /* Increased from 60px */
|
|
1278
|
+
padding: 6px !important;
|
|
1279
|
+
margin-bottom: 0.5rem !important; /* Reduced from 1rem */
|
|
1280
|
+
/* Reduced bottom padding to minimize empty space */
|
|
1281
|
+
padding-bottom: 0.5rem !important; /* Reduced from 1.5rem */
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
.editor-container,
|
|
1285
|
+
.proxy-editor-container {
|
|
1286
|
+
height: 140px !important; /* Increased from 100px */
|
|
1287
|
+
max-height: 140px !important;
|
|
1288
|
+
min-height: 120px !important; /* Increased from 80px */
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
/* Reduce editor height when JSON error is showing in very short landscape */
|
|
1292
|
+
.editor-container.has-error {
|
|
1293
|
+
height: 90px !important; /* Reduced to make room for error message */
|
|
1294
|
+
max-height: 90px !important;
|
|
1295
|
+
min-height: 80px !important;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
/* Ensure proxy editor takes full space in very short landscape */
|
|
1299
|
+
.proxy-editor {
|
|
1300
|
+
height: 100% !important;
|
|
1301
|
+
min-height: 100% !important;
|
|
1302
|
+
font-size: 10px !important;
|
|
1303
|
+
line-height: 1.3 !important;
|
|
1304
|
+
padding: 4px !important;
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
.code-editor {
|
|
1308
|
+
font-size: 10px !important;
|
|
1309
|
+
line-height: 1.3 !important;
|
|
1310
|
+
padding: 4px !important;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
/* Ensure syntax highlighting works in very short landscape */
|
|
1314
|
+
.code-highlight {
|
|
1315
|
+
font-size: 10px !important;
|
|
1316
|
+
line-height: 1.3 !important;
|
|
1317
|
+
padding: 4px !important;
|
|
1318
|
+
color: #f8f8f2 !important;
|
|
1319
|
+
opacity: 1 !important;
|
|
1320
|
+
display: block !important;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/* Ultra-compact error messages for very short landscape */
|
|
1324
|
+
.error-container {
|
|
1325
|
+
margin: 1px 0 !important;
|
|
1326
|
+
padding: 2px 4px !important;
|
|
1327
|
+
font-size: 8px !important;
|
|
1328
|
+
border-radius: 3px !important;
|
|
1329
|
+
gap: 4px !important;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
.error-icon {
|
|
1333
|
+
width: 10px !important;
|
|
1334
|
+
height: 10px !important;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
.error-icon svg {
|
|
1338
|
+
width: 10px !important;
|
|
1339
|
+
height: 10px !important;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
.error-title {
|
|
1343
|
+
font-size: 8px !important;
|
|
1344
|
+
margin-bottom: 1px !important;
|
|
1345
|
+
font-weight: 500 !important;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
.error-text {
|
|
1349
|
+
font-size: 7px !important;
|
|
1350
|
+
line-height: 1.1 !important;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/* Section divider */
|
|
1355
|
+
.section-divider {
|
|
1356
|
+
margin: 12px 0 !important;
|
|
1357
|
+
/* Reduce glow effect in landscape */
|
|
1358
|
+
box-shadow: 0 0 4px rgba(61, 62, 68, 0.2) !important;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/* Compact section headers in landscape */
|
|
1362
|
+
.admin-editor-section h5,
|
|
1363
|
+
.proxy-editor-section h5 {
|
|
1364
|
+
padding-bottom: 4px !important;
|
|
1365
|
+
|
|
1366
|
+
&::after {
|
|
1367
|
+
width: 30px !important;
|
|
1368
|
+
height: 1px !important;
|
|
1369
|
+
}
|
|
317
1370
|
}
|
|
318
1371
|
</style>
|