Skip to content

Commit edbbe24

Browse files
committed
Option for disabling File System Access API
1 parent 06a6c0d commit edbbe24

File tree

19 files changed

+122
-30
lines changed

19 files changed

+122
-30
lines changed

Diff for: lib/bootstrap/loader.mjs

+5
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,14 @@ export default function(content, map, meta) {
3535
],
3636
variables: [
3737
"--bs-primary",
38+
"--bs-black",
39+
/^--bs-gray/,
3840
/^--bs-btn-disabled/,
3941
/^--bs-nav-tabs/,
4042
],
43+
greedy: [
44+
/tooltip-arrow/,
45+
],
4146
},
4247
variables: true,
4348
})

Diff for: src/app/services/handleService.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { reactive, watch } from "vue";
1+
import { computed, reactive, watch } from "vue";
22
import * as idbKeyval from "idb-keyval"; // This library is really tiny, so it's OK to bundle
33

44
import { isFileApiEnabled } from "app/shared/constants";
55
import Workspace from "./workspaceService";
6+
import settings from "./settingService";
67

78
import type { ProjId } from "shared/json";
89

910
namespace HandleService {
1011

12+
export const enabled = computed(() => isFileApiEnabled && settings.useFileSystem);
13+
1114
export const recent: FileSystemFileHandle[] = reactive([]);
1215

1316
const handles: Map<ProjId, FileSystemFileHandle> = reactive(new Map());
@@ -45,7 +48,7 @@ namespace HandleService {
4548
}
4649

4750
export async function load(haveSession: boolean): Promise<void> {
48-
if(!isFileApiEnabled) return;
51+
if(!enabled.value) return;
4952
if(haveSession) {
5053
const entries: [number, FileSystemFileHandle][] = await idbKeyval.get("handle") || [];
5154
for(const [i, handle] of entries) handles.set(Workspace.ids.value[i], handle);
@@ -54,13 +57,13 @@ namespace HandleService {
5457
}
5558

5659
export async function getRecent(): Promise<void> {
57-
if(!isFileApiEnabled) return;
60+
if(!enabled.value) return;
5861
recent.length = 0;
5962
recent.push(...await idbKeyval.get("recent") || []);
6063
}
6164

6265
export async function save(): Promise<void> {
63-
if(!isFileApiEnabled) return;
66+
if(!enabled.value) return;
6467

6568
const entries: [number, FileSystemFileHandle][] = [];
6669
const ids = Workspace.ids.value;

Diff for: src/app/services/settingService.ts

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const DEFAULT_HOTKEY: KeyStore = {
5252
*/
5353
const defaultSettings = {
5454
autoSave: true,
55+
useFileSystem: true,
5556
loadSessionOnQueue: false,
5657
showDPad: true,
5758
showStatus: true,

Diff for: src/app/vue/gadgets/file/uploader.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div>
33
<input type="file" :id="id" :accept="type" :multiple="multiple" class="d-none" @change="upload($event)" />
4-
<label class="dropdown-item m-0" :for="id" ref="lbl">
4+
<label :class="labelCls ?? 'dropdown-item m-0'" :for="id" ref="lbl">
55
<slot></slot>
66
</label>
77
</div>
@@ -21,6 +21,7 @@
2121
const props = defineProps<{
2222
accept: string;
2323
multiple?: boolean;
24+
labelCls?: string;
2425
}>();
2526
2627
const type = computed(() =>

Diff for: src/app/vue/gadgets/form/toggle.vue

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<label class="form-check-label" v-bind:for="id">
88
<slot></slot>
99
</label>
10+
<slot name="append"></slot>
1011
</div>
1112
</div>
1213
</div>

Diff for: src/app/vue/gadgets/help.vue

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<template>
2+
<i ref="el" class="fa-solid fa-circle-info text-info ms-2" data-bs-toggle="tooltip" :data-bs-title="title"></i>
3+
</template>
4+
5+
<script setup lang="ts">
6+
import { onMounted, shallowRef } from "vue";
7+
8+
defineOptions({ name: "Help" });
9+
defineProps<{
10+
title: string;
11+
}>();
12+
13+
const el = shallowRef<HTMLElement>();
14+
15+
onMounted(() => {
16+
import("bootstrap/js/dist/tooltip").then(tp => tp.default.getOrCreateInstance(el.value!));
17+
});
18+
</script>
19+
20+
<style>
21+
.tooltip {
22+
--bs-tooltip-opacity: 1 !important;
23+
--bs-tooltip-bg: var(--bs-gray-200) !important;
24+
--bs-tooltip-color: var(--bs-black) !important;
25+
}
26+
27+
.tooltip-inner {
28+
text-align: left !important;
29+
}
30+
31+
html.dark {
32+
.tooltip {
33+
--bs-tooltip-bg: var(--bs-gray-800) !important;
34+
--bs-tooltip-color: var(--bs-white) !important;
35+
}
36+
}
37+
</style>

Diff for: src/app/vue/modals/components/export.vue

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</div>
88
<div class="modal-body">
99
<slot></slot>
10-
<div class="row mb-2" v-if="!isFileApiEnabled">
10+
<div class="row mb-2" v-if="!HandleService.enabled.value">
1111
<div class="col col-form-label flex-grow-0">{{ $t("keyword.filename") }}</div>
1212
<div class="col flex-grow-1">
1313
<input type="text" class="form-control" v-model="extFilename" />
@@ -18,7 +18,7 @@
1818
<button disabled v-if="!url" type="button" class="btn btn-lg btn-success">
1919
<i class="bp-spinner fa-spin" />
2020
</button>
21-
<CheckButton v-else-if="isFileApiEnabled" ref="bt" type="button" class="btn btn-lg btn-success"
21+
<CheckButton v-else-if="HandleService.enabled.value" ref="bt" type="button" class="btn btn-lg btn-success"
2222
@click="save">
2323
{{ $t("keyword.export") }}
2424
</CheckButton>
@@ -40,7 +40,8 @@
4040
4141
import Studio from "app/services/studioService";
4242
import useModal from "../modal";
43-
import { isFileApiEnabled, isInApp } from "app/shared/constants";
43+
import { isInApp } from "app/shared/constants";
44+
import HandleService from "app/services/handleService";
4445
import FileUtility from "app/utils/fileUtility";
4546
import { compRef } from "app/utils/compRef";
4647
import CheckButton from "@/gadgets/form/checkButton.vue";

Diff for: src/app/vue/modals/modalFragment.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<template v-if="phase >= 8">
1111
<Share :ref="mdlRef('share')" />
1212
<CP :ref="mdlRef('cp')" />
13-
<template v-if="!isFileApiEnabled">
13+
<template v-if="!HandleService.enabled.value">
1414
<SVG_ :ref="mdlRef('svg')" />
1515
<PNG :ref="mdlRef('png')" />
1616
<BPS :ref="mdlRef('bps')" />
@@ -25,7 +25,7 @@
2525

2626
<script setup lang="ts">
2727
28-
import { isFileApiEnabled } from "app/shared/constants";
28+
import HandleService from "app/services/handleService";
2929
import { phase } from "app/misc/phase";
3030
import { modals } from "./modals";
3131
import Share from "./share.vue";

Diff for: src/app/vue/modals/preference.vue

+11-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<button class="nav-link" :class="{ active: tab == 1 }" @click="tab = 1">{{
1313
$t("preference.color._") }}</button>
1414
<button class="nav-link" :class="{ active: tab == 2 }" @click="tab = 2">{{ $t("preference.hotkey")
15-
}}</button>
15+
}}</button>
1616
</div>
1717
</div>
1818
<!--
@@ -61,9 +61,15 @@
6161
<Toggle v-model="Settings.autoSave">
6262
{{ $t('preference.autoSave') }}
6363
</Toggle>
64-
<Toggle v-if="isFileApiEnabled" v-model="Settings.loadSessionOnQueue">
65-
{{ $t('preference.loadSessionOnQueue') }}
66-
</Toggle>
64+
<template v-if="isFileApiEnabled">
65+
<Toggle v-model="Settings.useFileSystem">
66+
<template v-slot:append><Help :title="$t('help.useFileSystem')" /></template>
67+
{{ $t('preference.useFileSystem') }}
68+
</Toggle>
69+
<Toggle v-model="Settings.loadSessionOnQueue">
70+
{{ $t('preference.loadSessionOnQueue') }}
71+
</Toggle>
72+
</template>
6773
<Toggle v-model="Settings.tools.SVG.includeHiddenElement">
6874
{{ $t('preference.includeHidden') }}
6975
</Toggle>
@@ -116,6 +122,7 @@
116122
import useModal from "./modal";
117123
import KeyTable from "./components/keyTable.vue";
118124
import Color from "./components/color.vue";
125+
import Help from "@/gadgets/help.vue";
119126
120127
defineOptions({ name: "Preference" });
121128

Diff for: src/app/vue/toolbar/fileMenu.vue

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</DropdownItem>
66
<Divider />
77

8-
<template v-if="isFileApiEnabled">
8+
<template v-if="Handles.enabled.value">
99
<Opener class="dropdown-item m-0" ref="opn" @open="open($event)" multiple>
1010
<Hotkey icon="far fa-folder-open" ctrl hk="O">{{ $t('toolbar.file.open') }}</Hotkey>
1111
</Opener>
@@ -40,7 +40,7 @@
4040

4141
<Divider />
4242

43-
<template v-if="isFileApiEnabled">
43+
<template v-if="Handles.enabled.value">
4444
<SaveAs :disabled="!Studio.project" type="svg" @save="svgSaved" :desc="$t('toolbar.file.SVG.name')" mime="image/svg+xml">
4545
<i class="far fa-file-image" />
4646
{{ $t('toolbar.file.SVG.save') }}
@@ -79,7 +79,7 @@
7979
import Workspace from "app/services/workspaceService";
8080
import Studio from "app/services/studioService";
8181
import HotKeyService from "app/services/hotkeyService";
82-
import { isFileApiEnabled, copyEnabled } from "app/shared/constants";
82+
import { copyEnabled } from "app/shared/constants";
8383
import Import from "app/services/importService";
8484
import { compRef } from "app/utils/compRef";
8585
import Handles from "app/services/handleService";
@@ -121,7 +121,7 @@
121121
}, "o");
122122
HotKeyService.register(() => {
123123
if(!Studio.project) return;
124-
if(isFileApiEnabled) save();
124+
if(Handles.enabled.value) save();
125125
else bps.value!.execute();
126126
}, "s");
127127
HotKeyService.register(() => Studio.project && bps.value!.execute(), "s", true); // Save as

Diff for: src/app/vue/welcome/fileList.vue

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
<template>
2-
<div v-if="Studio.initialized && isFileApiEnabled" class="row mt-4 mt-sm-5 justify-content-center file-api">
2+
<div v-if="Studio.initialized" class="row mt-4 mt-sm-5 justify-content-center file-api">
33
<div class="col-12 col-sm-6 col-lg-5 col-xl-4 mb-4">
44
<div class="h4 mb-3">{{ $t("welcome.start") }}</div>
55
<div @click="Workspace.create()" class="quick-item">
66
<i class="bp-file fa-fw me-2" />
77
<span>{{ $t("toolbar.file.new") }}</span>
88
</div>
9-
<Opener @open="Import.open($event, false)" multiple class="quick-item">
9+
<Opener v-if="handles.enabled.value" @open="Import.open($event, false)" multiple class="quick-item">
1010
<i class="bp-folder-open fa-fw me-2" />
1111
<span>{{ $t('toolbar.file.open') }}</span>
1212
</Opener>
13+
<Uploader v-else accept=".bps, .bpz, .json, .zip" multiple @upload="upload($event)" class="quick-item" label-cls="">
14+
<i class="bp-folder-open fa-fw me-2" />
15+
<span>{{ $t('toolbar.file.open') }}</span>
16+
</Uploader>
1317
</div>
1418
<div class="col-12 col-sm-6 col-lg-5 col-xl-4 recent">
15-
<div v-if="handles.recent.length">
19+
<div v-if="handles.enabled.value && handles.recent.length">
1620
<div class="h4 mb-3">{{ $t("welcome.recent") }}</div>
1721
<div v-for="(h, i) in handles.recent" :key="i" @click="Import.open([h], true)" class="quick-item">
1822
{{ h.name }}
@@ -25,12 +29,15 @@
2529
<script setup lang="ts">
2630
2731
import handles from "app/services/handleService";
28-
import { isFileApiEnabled } from "app/shared/constants";
29-
import Opener from "@/gadgets/file/opener.vue";
3032
import Studio from "app/services/studioService";
3133
import Workspace from "app/services/workspaceService";
3234
import Import from "app/services/importService";
35+
import { Uploader, Opener } from "@/gadgets/file";
3336
3437
defineOptions({ name: "FileList" });
3538
39+
async function upload(files: FileList): Promise<void> {
40+
await Import.openFiles(files);
41+
}
42+
3643
</script>

Diff for: src/locale/en.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@
145145
"confirmKey": "Hotkey {0} is already assigned to the command \"{1}\"; would you like to replace it?",
146146
"autoSave": "Save workspace automatically",
147147
"includeHidden": "Include hidden elements in SVG exports",
148-
"loadSessionOnQueue": "Load previous session when directly open a project file"
148+
"loadSessionOnQueue": "Load previous session when directly open a project file",
149+
"useFileSystem": "Use file system API"
149150
},
150151
"panel": {
151152
"design": {
@@ -311,5 +312,8 @@
311312
"untitled": "Untitled",
312313
"errorLog": "Download error log",
313314
"workspace": "workspace"
315+
},
316+
"help": {
317+
"useFileSystem": "Enabling this allows you to directly save into editing files and keep a record of recently opened files. You can disable this if you encounter any trouble opening files on mobile devices."
314318
}
315319
}

Diff for: src/locale/es.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@
145145
"confirmKey": "La tecla de acceso rápido {0} ya está asignada al comando \"{1}\"; ¿te gustaría reemplazarlo?",
146146
"autoSave": "Guardar el espacio de trabajo automáticamente",
147147
"includeHidden": "Incluir elementos ocultos en las exportaciones SVG",
148-
"loadSessionOnQueue": "Cargar la sesión anterior al abrir directamente un archivo de proyecto"
148+
"loadSessionOnQueue": "Cargar la sesión anterior al abrir directamente un archivo de proyecto",
149+
"useFileSystem": "Utilice la API del sistema de archivos"
149150
},
150151
"panel": {
151152
"design": {
@@ -311,5 +312,8 @@
311312
"untitled": "Sin título",
312313
"errorLog": "Descargar registro de errores",
313314
"workspace": "espacio de trabajo"
315+
},
316+
"help": {
317+
"useFileSystem": "Habilitar esto le permite guardar directamente en los archivos de edición y mantener un registro de archivos abiertos recientemente. Puede deshabilitar esto si encuentra algún problema para abrir archivos en dispositivos móviles."
314318
}
315319
}

Diff for: src/locale/ja.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@
145145
"confirmKey": "ホットキー {0} はすでにコマンド「{1}」に割り当てられています。交換しますか?",
146146
"autoSave": "ワークスペースを自動的に保存",
147147
"includeHidden": "SVG エクスポートに非表示の要素を含める",
148-
"loadSessionOnQueue": "プロジェクトファイルを直接開くときに前のセッションをロードする"
148+
"loadSessionOnQueue": "プロジェクトファイルを直接開くときに前のセッションをロードする",
149+
"useFileSystem": "ファイルシステム API を使用します"
149150
},
150151
"panel": {
151152
"design": {
@@ -311,5 +312,8 @@
311312
"untitled": "無題",
312313
"errorLog": "ダウンロードエラーログ",
313314
"workspace": "ワークスペース"
315+
},
316+
"help": {
317+
"useFileSystem": "これを有効にすると、ファイルの編集に直接保存し、最近開かれたファイルのレコードを保持できます。モバイルデバイスでファイルを開くのに問題が発生した場合、これを無効にできます。"
314318
}
315319
}

Diff for: src/locale/ko.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@
145145
"confirmKey": "단축키 {0} 은(는) 이미 \"{1}\" 명령에 할당되었습니다. 교체하시겠습니까?",
146146
"autoSave": "자동으로 작업 공간 저장",
147147
"includeHidden": "SVG 내보내기에 숨겨진 요소 포함",
148-
"loadSessionOnQueue": "프로젝트 파일을 직접 열 때 이전 세션 로드"
148+
"loadSessionOnQueue": "프로젝트 파일을 직접 열 때 이전 세션 로드",
149+
"useFileSystem": "파일 시스템 API 를 사용하십시오"
149150
},
150151
"panel": {
151152
"design": {
@@ -311,5 +312,8 @@
311312
"untitled": "무제",
312313
"errorLog": "오류 로그 다운로드",
313314
"workspace": "작업 공간"
315+
},
316+
"help": {
317+
"useFileSystem": "이를 활성화하면 파일 편집에 직접 저장하고 최근에 열린 파일의 레코드를 유지할 수 있습니다. 모바일 장치에서 파일을 열는 데 문제가 발생하면이를 비활성화 할 수 있습니다."
314318
}
315319
}

Diff for: src/locale/vi.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@
145145
"confirmKey": "Phím nóng {0} đã được gán cho lệnh \"{1}\"; bạn có muốn thay thế nó không?",
146146
"autoSave": "Tự động lưu không gian làm việc",
147147
"includeHidden": "Bao gồm các yếu tố ẩn trong xuất SVG",
148-
"loadSessionOnQueue": "Tải phiên trước khi mở trực tiếp tệp dự án"
148+
"loadSessionOnQueue": "Tải phiên trước khi mở trực tiếp tệp dự án",
149+
"useFileSystem": "Sử dụng API hệ thống tệp"
149150
},
150151
"panel": {
151152
"design": {
@@ -311,5 +312,8 @@
311312
"untitled": "Không có tiêu đề",
312313
"errorLog": "Tải xuống nhật ký lỗi",
313314
"workspace": "không gian làm việc"
315+
},
316+
"help": {
317+
"useFileSystem": "Kích hoạt điều này cho phép bạn lưu trực tiếp vào các tệp chỉnh sửa và lưu giữ bản ghi các tệp được mở gần đây. Bạn có thể vô hiệu hóa điều này nếu bạn gặp bất kỳ sự cố nào mở các tệp trên thiết bị di động."
314318
}
315319
}

0 commit comments

Comments
 (0)