forked from akai/readest
This commit is contained in:
@@ -323,7 +323,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
};
|
||||
|
||||
const handleOpenWithBooks = async (appService: AppService, library: Book[]) => {
|
||||
const openWithFiles = (await parseOpenWithFiles()) || [];
|
||||
const openWithFiles = (await parseOpenWithFiles(appService)) || [];
|
||||
|
||||
if (openWithFiles.length > 0) {
|
||||
return await processOpenWithFiles(appService, openWithFiles, library);
|
||||
|
||||
@@ -178,7 +178,7 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
|
||||
}
|
||||
dismissBook(bookKey);
|
||||
if (bookKeys.filter((key) => key !== bookKey).length == 0) {
|
||||
const openWithFiles = (await parseOpenWithFiles()) || [];
|
||||
const openWithFiles = (await parseOpenWithFiles(appService)) || [];
|
||||
if (appService?.hasWindow) {
|
||||
if (openWithFiles.length > 0) {
|
||||
tauriHandleOnCloseWindow(handleCloseBooks);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { isWebAppPlatform, hasCli } from '@/services/environment';
|
||||
import { AppService } from '@/types/system';
|
||||
import { getCurrent } from '@tauri-apps/plugin-deep-link';
|
||||
|
||||
declare global {
|
||||
@@ -35,14 +36,18 @@ const parseCLIOpenWithFiles = async () => {
|
||||
return files;
|
||||
};
|
||||
|
||||
const parseIntentOpenWithFiles = async () => {
|
||||
const parseIntentOpenWithFiles = async (appService: AppService | null) => {
|
||||
const urls = await getCurrent();
|
||||
if (urls && urls.length > 0) {
|
||||
console.log('Intent Open with URL:', urls);
|
||||
return urls
|
||||
.map((url) => {
|
||||
if (url.startsWith('file://')) {
|
||||
return decodeURI(url.replace('file://', ''));
|
||||
if (appService?.isIOSApp) {
|
||||
return decodeURI(url);
|
||||
} else {
|
||||
return decodeURI(url.replace('file://', ''));
|
||||
}
|
||||
} else if (url.startsWith('content://')) {
|
||||
return url;
|
||||
} else {
|
||||
@@ -55,7 +60,7 @@ const parseIntentOpenWithFiles = async () => {
|
||||
return null;
|
||||
};
|
||||
|
||||
export const parseOpenWithFiles = async () => {
|
||||
export const parseOpenWithFiles = async (appService: AppService | null) => {
|
||||
if (isWebAppPlatform()) return [];
|
||||
|
||||
let files = parseWindowOpenWithFiles();
|
||||
@@ -63,7 +68,7 @@ export const parseOpenWithFiles = async () => {
|
||||
files = await parseCLIOpenWithFiles();
|
||||
}
|
||||
if (!files || files.length === 0) {
|
||||
files = await parseIntentOpenWithFiles();
|
||||
files = await parseIntentOpenWithFiles(appService);
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const DEFAULT_SHORTCUTS = {
|
||||
onSwitchSideBar: ['ctrl+Tab', 'opt+Tab', 'alt+Tab'],
|
||||
onToggleSideBar: ['s', 'F9'],
|
||||
onToggleSideBar: ['s'],
|
||||
onToggleNotebook: ['n'],
|
||||
onShowSearchBar: ['ctrl+f', 'cmd+f'],
|
||||
onToggleScrollMode: ['shift+j'],
|
||||
|
||||
@@ -36,7 +36,11 @@ export function useOpenWithBooks() {
|
||||
const filePaths = [];
|
||||
for (let url of urls) {
|
||||
if (url.startsWith('file://')) {
|
||||
url = decodeURI(url.replace('file://', ''));
|
||||
if (appService?.isIOSApp) {
|
||||
url = decodeURI(url);
|
||||
} else {
|
||||
url = decodeURI(url.replace('file://', ''));
|
||||
}
|
||||
}
|
||||
if (!/^(https?:|data:|blob:)/i.test(url)) {
|
||||
filePaths.push(url);
|
||||
@@ -73,20 +77,27 @@ export function useOpenWithBooks() {
|
||||
if (listenedOpenWithBooks.current) return;
|
||||
listenedOpenWithBooks.current = true;
|
||||
|
||||
const unlistenDeeplink = getCurrentWindow().listen('single-instance', ({ event, payload }) => {
|
||||
console.log('Received deep link:', event, payload);
|
||||
const { args } = payload as SingleInstancePayload;
|
||||
if (args?.[1]) {
|
||||
handleOpenWithFileUrl([args[1]]);
|
||||
}
|
||||
});
|
||||
// For Windows/Linux deep link and macOS open-file event
|
||||
const unlistenDeeplink = getCurrentWindow().listen<SingleInstancePayload>(
|
||||
'single-instance',
|
||||
({ event, payload }) => {
|
||||
console.log('Received deep link:', event, payload);
|
||||
const { args } = payload;
|
||||
if (args?.[1]) {
|
||||
handleOpenWithFileUrl([args[1]]);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// For Android "Share to Readest" intent
|
||||
let unlistenSharedIntent: Promise<PluginListener> | null = null;
|
||||
// FIXME: register/unregister plugin listeniner on iOS might cause app freeze for unknown reason
|
||||
// so we only register it on Android for now to support "Shared to Readest" feature
|
||||
if (appService?.isAndroidApp) {
|
||||
unlistenSharedIntent = initializeListeners();
|
||||
}
|
||||
|
||||
// iOS Open with URL event
|
||||
const listenOpenWithFiles = async () => {
|
||||
return await onOpenUrl((urls) => {
|
||||
handleOpenWithFileUrl(urls);
|
||||
|
||||
@@ -194,7 +194,7 @@ export const nativeFileSystem: FileSystem = {
|
||||
let fname = name || getFilename(fp);
|
||||
if (isValidURL(path)) {
|
||||
return await new RemoteFile(path, fname).open();
|
||||
} else if (isContentURI(path)) {
|
||||
} else if (isContentURI(path) || (isFileURI(path) && OS_TYPE === 'ios')) {
|
||||
fname = await basename(path);
|
||||
if (path.includes('com.android.externalstorage')) {
|
||||
// If the URI is from shared internal storage (like /storage/emulated/0),
|
||||
@@ -202,6 +202,7 @@ export const nativeFileSystem: FileSystem = {
|
||||
return await new NativeFile(fp, fname, baseDir ? baseDir : null).open();
|
||||
} else {
|
||||
// Otherwise, for content:// URIs (e.g. from MediaStore, Drive, or third-party apps),
|
||||
// or file:// URIs is security scoped resource in iOS (e.g. from Files app),
|
||||
// we cannot access the file directly — so we copy it to a temporary cache location.
|
||||
const prefix = await this.getPrefix('Cache');
|
||||
const dst = await join(prefix, fname);
|
||||
|
||||
Reference in New Issue
Block a user