Compare commits

...

11 Commits

13 changed files with 82 additions and 46 deletions
+8 -4
View File
@@ -7,13 +7,17 @@ assignees: ''
---
**Does your feature request involve difficulty for you to complete a task? Please describe.**
A clear and concise description of what the problem is. Ex. I think it takes too many steps to [...]
> A clear and concise description of what the problem is. Ex. I think it takes too many steps to [...]
**Describe the solution you'd like**
A clear and concise description of what you'd like to happen.
> A clear and concise description of what you'd like to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
> A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any additional context or screenshots about the feature request here.
> Add any additional context or screenshots about the feature request here.
+10 -19
View File
@@ -11,22 +11,16 @@ assignees: ''
A clear and concise description of what the current behavior is.
Please also add **screenshots** of the existing application.
**Example:**
```
In DarkMode, when scrollbar are displayed (for example on Companies page, with enough companies in the list), we see a blank square in the bottom right corner
[screenshot]
```
> **Example:**
> In DarkMode, when scrollbar are displayed (for example on Companies page, with enough companies in the list), we see a blank square in the bottom right corner
> [screenshot]
## Expected behavior
A clear and concise description of what the expected behavior is.
**Example:**
```
The blank square should be transparent (invisible)
```
> **Example:**
> The blank square should be transparent (invisible)
## Technical inputs
@@ -34,11 +28,8 @@ Operating System:
Readest Version:
**Example:**
```
Operating System: macOS 14.3.1
Readest Version: 0.9.0
We are displaying custom scrollbars that disappear when the user is not scrolling. See ScrollWrapper.
Probably fixable with CSS
```
> **Example:**
> Operating System: Android 14 (WebView 135.0)
> Readest Version: 0.9.0
> We are displaying custom scrollbars that disappear when the user is not scrolling. See ScrollWrapper.
> Probably fixable with CSS
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@readest/readest-app",
"version": "0.9.39",
"version": "0.9.40",
"private": true,
"scripts": {
"dev": "dotenv -e .env.tauri -- next dev",
+10
View File
@@ -1,5 +1,15 @@
{
"releases": {
"0.9.40": {
"date": "2025-05-08",
"notes": [
"Prevented oversized images from causing layout issues",
"Resolved issue with transient navigation bar on Android 9",
"Action bar now closes properly when the footbar is dismissed",
"Smoother experience when expanding Table of Contents sections",
"Reverted unintended style overrides"
]
},
"0.9.39": {
"date": "2025-05-07",
"notes": [
@@ -225,7 +225,7 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
controller.hide(WindowInsets.Type.systemBars())
}
}
} else {
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val compatController = WindowCompat.getInsetsController(window, decorView)
compatController?.let {
it.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
@@ -240,6 +240,21 @@ class NativeBridgePlugin(private val activity: Activity): Plugin(activity) {
it.hide(WindowInsetsCompat.Type.systemBars())
}
}
} else {
@Suppress("DEPRECATION")
decorView.systemUiVisibility = when {
visible && !isDarkMode -> View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
visible -> View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
else -> View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_FULLSCREEN
}
}
window.statusBarColor = Color.TRANSPARENT
window.navigationBarColor = Color.TRANSPARENT
+1 -1
View File
@@ -121,7 +121,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
useEffect(() => {
if (appService?.isMobileApp) {
lockScreenOrientation({ orientation: 'portrait' });
lockScreenOrientation({ orientation: 'auto' });
}
}, [appService]);
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import clsx from 'clsx';
import { RiArrowLeftWideLine, RiArrowRightWideLine } from 'react-icons/ri';
import { RiArrowGoBackLine, RiArrowGoForwardLine } from 'react-icons/ri';
@@ -122,6 +122,12 @@ const FooterBar: React.FC<FooterBarProps> = ({
}
};
useEffect(() => {
if (hoveredBookKey !== bookKey) {
setActionTab('');
}
}, [hoveredBookKey, bookKey]);
const getMarginProgressValue = (marginPx: number, gapPercent: number) => {
return (marginPx / 88 + gapPercent / 10) * 50;
};
@@ -123,7 +123,7 @@ const TOCView: React.FC<{
toc: TOCItem[];
}> = ({ bookKey, toc }) => {
const { getProgress } = useReaderStore();
const { sideBarBookKey } = useSidebarStore();
const { sideBarBookKey, isSideBarVisible } = useSidebarStore();
const progress = getProgress(bookKey);
const [expandedItems, setExpandedItems] = useState<string[]>([]);
@@ -146,9 +146,6 @@ const TOCView: React.FC<{
}
(currentItem as HTMLElement).setAttribute('aria-current', 'page');
}
if (currentHref) {
expandParents(toc, currentHref);
}
};
useEffect(() => {
@@ -165,13 +162,19 @@ const TOCView: React.FC<{
}
return () => observer.disconnect();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [viewRef]);
}, [viewRef.current]);
useEffect(() => {
if (!progress || eventDispatcher.dispatchSync('tts-is-speaking')) return;
if (sideBarBookKey !== bookKey) return;
if (!isSideBarVisible) return;
const { sectionHref: currentHref } = progress;
if (currentHref) {
expandParents(toc, currentHref);
}
scrollToProgress(progress);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [toc, progress, sideBarBookKey]);
}, [toc, progress, sideBarBookKey, isSideBarVisible]);
return (
<div className='rounded pt-2'>
+4 -1
View File
@@ -1,5 +1,6 @@
import React from 'react';
import clsx from 'clsx';
import React from 'react';
import { useEnv } from '@/context/EnvContext';
interface ButtonProps {
icon: React.ReactNode;
@@ -18,6 +19,7 @@ const Button: React.FC<ButtonProps> = ({
tooltipDirection = 'top',
className,
}) => {
const { appService } = useEnv();
return (
<div
className={clsx(
@@ -32,6 +34,7 @@ const Button: React.FC<ButtonProps> = ({
<button
className={clsx(
'btn btn-ghost h-8 min-h-8 w-8 p-0',
appService?.isMobileApp && 'hover:bg-transparent',
disabled && 'btn-disabled !bg-transparent',
className,
)}
+2 -1
View File
@@ -43,7 +43,7 @@ const Dialog: React.FC<DialogProps> = ({
const { appService } = useEnv();
const { systemUIVisible, statusBarHeight } = useThemeStore();
const { acquireBackKeyInterception, releaseBackKeyInterception } = useDeviceControlStore();
const [isFullHeightInMobile, setIsFullHeightInMobile] = React.useState(!snapHeight);
const [isFullHeightInMobile, setIsFullHeightInMobile] = useState(!snapHeight);
const [isRtl] = useState(() => getDirFromUILanguage() === 'rtl');
const iconSize22 = useResponsiveSize(22);
const isMobile = window.innerWidth < 640;
@@ -62,6 +62,7 @@ const Dialog: React.FC<DialogProps> = ({
useEffect(() => {
if (!isOpen) return;
setIsFullHeightInMobile(!snapHeight);
window.addEventListener('keydown', handleKeyDown);
if (appService?.isAndroidApp) {
acquireBackKeyInterception();
+10 -7
View File
@@ -87,12 +87,12 @@ const getFontStyles = (
body * {
${overrideFont ? 'font-family: revert !important;' : ''}
}
a:any-link * {
a:any-link, a:any-link * {
${overrideFont ? `color: ${primary};` : ''}
}
/* https://github.com/whatwg/html/issues/5426 */
@media (prefers-color-scheme: dark) {
a:link * {
a:any-link, a:any-link * {
${overrideFont ? `color: ${primary};` : `color: lightblue;`}
}
}
@@ -210,6 +210,8 @@ const getLayoutStyles = (
${writingMode === 'auto' ? '' : `writing-mode: ${writingMode} !important;`}
text-align: var(--default-text-align);
max-height: unset;
}
html {
background-color: var(--theme-bg-color, transparent);
background: var(--background-set, none);
}
@@ -223,7 +225,7 @@ const getLayoutStyles = (
svg, img {
background-color: transparent !important;
}
p:not(.poem):not(.poetry):not(.lh):not(:has(> :is(img, video, font, b, h1, h2, h3, h4, h5, table))), li, blockquote, dd {
p, li, blockquote, dd {
line-height: ${lineSpacing} ${overrideLayout ? '!important' : ''};
word-spacing: ${wordSpacing}px ${overrideLayout ? '!important' : ''};
letter-spacing: ${letterSpacing}px ${overrideLayout ? '!important' : ''};
@@ -262,6 +264,11 @@ const getLayoutStyles = (
display: none;
}
img {
height: auto;
width: auto;
}
img.pi {
${vertical ? 'transform: rotate(90deg);' : ''}
${vertical ? 'transform-origin: center;' : ''}
@@ -280,10 +287,6 @@ const getLayoutStyles = (
display: none;
}
.duokan-image-single {
height: 100vh !important;
}
.calibre {
color: unset;
}
+3 -3
View File
@@ -95,7 +95,7 @@ export class TxtToEpubConverter {
): Chapter[] {
const { language } = metadata;
const { linesBetweenSegments } = option;
const segmentRegex = new RegExp(`(?:\\r?\\n){${linesBetweenSegments},}|-{4,}\r?\n`);
const segmentRegex = new RegExp(`(?:\\r?\\n){${linesBetweenSegments},}|-{8,}\r?\n`);
let chapterRegex: RegExp;
if (language === 'zh') {
chapterRegex = new RegExp(
@@ -117,7 +117,7 @@ export class TxtToEpubConverter {
const formatSegment = (segment: string): string => {
segment = escapeXml(segment);
return segment
.replace(/-{4,}|_{4,}/g, '\n')
.replace(/-{8,}|_{8,}/g, '\n')
.split(/\n+/)
.map((line) => line.trim())
.filter((line) => line)
@@ -156,7 +156,7 @@ export class TxtToEpubConverter {
let isVolume = false;
if (language === 'zh') {
isVolume = /第[一二三四五六七八九十百千万0-9]+卷/.test(title);
isVolume = /第[零〇一二三四五六七八九十百千万0-9]+卷/.test(title);
} else {
isVolume = /\b(Part|Volume|Book)\b/i.test(title);
}