forked from akai/readest
This commit is contained in:
@@ -20,12 +20,43 @@
|
||||
android:label="@string/main_activity_title"
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter android:label="oauth">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="readest" android:host="auth-callback" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="content" />
|
||||
<data android:scheme="file" />
|
||||
|
||||
<data android:mimeType="application/epub+zip" />
|
||||
<data android:mimeType="application/pdf" />
|
||||
<data android:mimeType="application/fb2" />
|
||||
<data android:mimeType="application/x-fb2" />
|
||||
<data android:mimeType="application/vnd.amazon.mobi8-ebook" />
|
||||
<data android:mimeType="application/vnd.comicbook+zip" />
|
||||
<data android:mimeType="application/x-cbz" />
|
||||
<data android:mimeType="application/x-mobipocket-ebook" />
|
||||
<data android:mimeType="application/zip" />
|
||||
<data android:mimeType="text/plain" />
|
||||
|
||||
<data android:pathPattern=".*\\.epub" />
|
||||
<data android:pathPattern=".*\\.pdf" />
|
||||
<data android:pathPattern=".*\\.fb2" />
|
||||
<data android:pathPattern=".*\\.fb2.zip" />
|
||||
<data android:pathPattern=".*\\.mobi" />
|
||||
<data android:pathPattern=".*\\.azw" />
|
||||
<data android:pathPattern=".*\\.cbz" />
|
||||
<data android:pathPattern=".*\\.zip" />
|
||||
<data android:pathPattern=".*\\.txt" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:label="oauth">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="readest" android:host="auth-callback" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
||||
-18
@@ -2,14 +2,10 @@ package com.bilingify.readest
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowInsetsController
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import app.tauri.plugin.JSObject
|
||||
import com.readest.native_bridge.NativeBridgePlugin
|
||||
|
||||
class MainActivity : TauriActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -19,20 +15,6 @@ class MainActivity : TauriActivity() {
|
||||
hideSystemUI()
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
|
||||
val uri = intent.data ?: return
|
||||
if (uri.scheme == "readest" && uri.host == "auth-callback") {
|
||||
val result = JSObject().apply {
|
||||
put("redirectUrl", uri.toString())
|
||||
}
|
||||
|
||||
NativeBridgePlugin.pendingInvoke?.resolve(result)
|
||||
NativeBridgePlugin.pendingInvoke = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideSystemUI() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
window.decorView.windowInsetsController?.let { controller ->
|
||||
|
||||
+35
@@ -4,6 +4,7 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import android.webkit.WebView
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import app.tauri.annotation.Command
|
||||
@@ -40,6 +41,40 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
|
||||
var pendingInvoke: Invoke? = null
|
||||
}
|
||||
|
||||
override fun load(webView: WebView) {
|
||||
super.load(webView)
|
||||
handleIntent(activity.intent)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
handleIntent(intent)
|
||||
}
|
||||
|
||||
private fun handleIntent(intent: Intent?) {
|
||||
val uri = intent?.data ?: return
|
||||
Log.e("NativeBridgePlugin", "Received intent: $uri")
|
||||
when {
|
||||
uri.scheme == "readest" && uri.host == "auth-callback" -> {
|
||||
val result = JSObject().apply {
|
||||
put("redirectUrl", uri.toString())
|
||||
}
|
||||
pendingInvoke?.resolve(result)
|
||||
pendingInvoke = null
|
||||
}
|
||||
|
||||
intent.action == Intent.ACTION_VIEW -> {
|
||||
try {
|
||||
activity.contentResolver.takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
} catch (e: SecurityException) {
|
||||
Log.e("NativeBridgePlugin", "Failed to take persistable URI permission: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command
|
||||
fun auth_with_custom_tab(invoke: Invoke) {
|
||||
val args = invoke.parseArgs(AuthRequestArgs::class.java)
|
||||
|
||||
@@ -175,16 +175,16 @@ const LibraryHeader: React.FC<LibraryHeaderProps> = ({
|
||||
<Dropdown
|
||||
className='exclude-title-bar-mousedown dropdown-bottom dropdown-end'
|
||||
buttonClassName='btn btn-ghost h-8 min-h-8 w-8 p-0'
|
||||
toggleButton={<MdOutlineMenu size={iconSize18} />}
|
||||
toggleButton={<PiDotsThreeCircle size={iconSize18} />}
|
||||
>
|
||||
<SettingsMenu />
|
||||
<SortMenu />
|
||||
</Dropdown>
|
||||
<Dropdown
|
||||
className='exclude-title-bar-mousedown dropdown-bottom dropdown-end'
|
||||
buttonClassName='btn btn-ghost h-8 min-h-8 w-8 p-0'
|
||||
toggleButton={<PiDotsThreeCircle size={iconSize18} />}
|
||||
toggleButton={<MdOutlineMenu size={iconSize18} />}
|
||||
>
|
||||
<SortMenu />
|
||||
<SettingsMenu />
|
||||
</Dropdown>
|
||||
{appService?.hasWindowBar && (
|
||||
<WindowButtons
|
||||
|
||||
@@ -12,7 +12,7 @@ import { getFilename, listFormater } from '@/utils/book';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { ProgressPayload } from '@/utils/transfer';
|
||||
import { throttle } from '@/utils/throttle';
|
||||
import { parseOpenWithFiles } from '@/helpers/cli';
|
||||
import { parseOpenWithFiles } from '@/helpers/openWith';
|
||||
import { isTauriAppPlatform } from '@/services/environment';
|
||||
import { checkForAppUpdates } from '@/helpers/updater';
|
||||
import { FILE_ACCEPT_FORMATS, SUPPORTED_FILE_EXTS } from '@/services/constants';
|
||||
@@ -204,7 +204,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
for (const file of openWithFiles) {
|
||||
console.log('Open with book:', file);
|
||||
try {
|
||||
const temp = !settings.autoImportBooksOnOpen;
|
||||
const temp = appService.isMobile ? false : !settings.autoImportBooksOnOpen;
|
||||
const book = await appService.importBook(file, libraryBooks, true, true, false, temp);
|
||||
if (book) {
|
||||
bookIds.push(book.hash);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useReaderStore } from '@/store/readerStore';
|
||||
import { useSidebarStore } from '@/store/sidebarStore';
|
||||
import { Book } from '@/types/book';
|
||||
import { SystemSettings } from '@/types/settings';
|
||||
import { parseOpenWithFiles } from '@/helpers/cli';
|
||||
import { parseOpenWithFiles } from '@/helpers/openWith';
|
||||
import { tauriHandleClose, tauriHandleOnCloseWindow } from '@/utils/window';
|
||||
import { isTauriAppPlatform } from '@/services/environment';
|
||||
import { uniqueId } from '@/utils/misc';
|
||||
@@ -135,7 +135,7 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
|
||||
dismissBook(bookKey);
|
||||
if (bookKeys.filter((key) => key !== bookKey).length == 0) {
|
||||
const openWithFiles = (await parseOpenWithFiles()) || [];
|
||||
if (openWithFiles.length > 0) {
|
||||
if (openWithFiles.length > 0 && !appService?.isMobile) {
|
||||
tauriHandleClose();
|
||||
} else {
|
||||
saveSettingsAndGoToLibrary();
|
||||
|
||||
@@ -200,8 +200,10 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const lineHeightValue =
|
||||
parseFloat(lineHeight) || viewSettings.lineHeight * viewSettings.defaultFontSize;
|
||||
const fontSizeValue = parseFloat(fontSize) || viewSettings.defaultFontSize;
|
||||
const strokeWidth = style === 'underline' ? 2 : 4;
|
||||
const padding = (lineHeightValue - fontSizeValue - strokeWidth) / 2;
|
||||
const strokeWidth = 2;
|
||||
const padding = viewSettings.vertical
|
||||
? (lineHeightValue - fontSizeValue - strokeWidth) / 2
|
||||
: strokeWidth;
|
||||
draw(Overlayer[style as keyof typeof Overlayer], { writingMode, color: hexColor, padding });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,9 +38,10 @@ const TTSControl = () => {
|
||||
const [timeoutTimestamp, setTimeoutTimestamp] = useState(0);
|
||||
const [timeoutFunc, setTimeoutFunc] = useState<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
const popupWidth = useResponsiveSize(POPUP_WIDTH);
|
||||
const popupHeight = useResponsiveSize(POPUP_HEIGHT);
|
||||
const popupPadding = useResponsiveSize(POPUP_PADDING);
|
||||
const maxWidth = window.innerWidth - 2 * popupPadding;
|
||||
const popupWidth = Math.min(maxWidth, useResponsiveSize(POPUP_WIDTH));
|
||||
const popupHeight = useResponsiveSize(POPUP_HEIGHT);
|
||||
|
||||
const iconRef = useRef<HTMLDivElement>(null);
|
||||
const ttsControllerRef = useRef<TTSController | null>(null);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { isWebAppPlatform, hasCli } from '@/services/environment';
|
||||
import { getCurrent } from '@tauri-apps/plugin-deep-link';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
OPEN_WITH_FILES?: string[];
|
||||
OPEN_WITH_FILES?: string[] | null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +33,28 @@ const parseCLIOpenWithFiles = async () => {
|
||||
return files;
|
||||
};
|
||||
|
||||
const parseIntentOpenWithFiles = async () => {
|
||||
const urls = await getCurrent();
|
||||
if (urls && urls.length > 0) {
|
||||
console.log('Intent Open with URL:', urls);
|
||||
const files = urls.map((url) => {
|
||||
if (url.startsWith('file://')) {
|
||||
return decodeURI(url.replace('file://', ''));
|
||||
}
|
||||
return url;
|
||||
});
|
||||
return files;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const parseOpenWithFiles = async () => {
|
||||
if (isWebAppPlatform()) return [];
|
||||
|
||||
let files = parseWindowOpenWithFiles();
|
||||
if (!files) {
|
||||
files = await parseIntentOpenWithFiles();
|
||||
}
|
||||
if (!files && hasCli()) {
|
||||
files = await parseCLIOpenWithFiles();
|
||||
}
|
||||
Reference in New Issue
Block a user