forked from lnreader/lnreader
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(settings): add custom code settings screen #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
CD-Z
wants to merge
28
commits into
master
Choose a base branch
from
custom_code_settings_page_clean
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
9c7800b
copied old code
CD-Z 725b231
clean up WebVieweReader
CD-Z 409ce50
update pnpm-lock.yaml
CD-Z d12d8e6
Update index.tsx
CD-Z 47c012f
Improve TextInput focus and keyboard behavior
CD-Z 5a26ed6
optimized app bar animation
CD-Z 6f7212b
Remove gap between keyboard and content
CD-Z 2e004b1
Update ToggleButton
CD-Z 11a4fad
Remove AdvancedTab from Reader settings
CD-Z eaa4d4c
added code migration
CD-Z 28a3d09
Update settings webview
CD-Z 6930a08
updated text remover modal
CD-Z 0f068b9
small fixes
CD-Z 030cf65
add stopPropagation
CD-Z 3490ce4
dismiss Keyboard on closing KeyboardAvoidingModal
CD-Z 09bc4b9
add simple regex validation
CD-Z 087548d
Update KeyboardAvoidingModal.tsx
CD-Z a0ba6b0
added localization
CD-Z b9966ae
Update useTextModifications.ts
CD-Z b110e1b
Update useTextModifications.ts
CD-Z 96d9946
updated KeyboardAvoidingModal
CD-Z aa9f8bc
Update SettingsReaderWebView.tsx
CD-Z 571b0b3
Update useTextModifications.ts
CD-Z 3c2e823
Update SettingsReaderWebView.tsx
CD-Z 9fac388
Update ReaderScreen.tsx
CD-Z 963fdd2
Update setting migration
CD-Z c590439
clone snippets on save
CD-Z 9ce82fb
fade out disabled ToggleButton
CD-Z File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,195 @@ | ||
| // Text selection functionality | ||
| window.textRemover = new (function () { | ||
| let selectionUI = null; | ||
| let isUIActive = false; | ||
|
|
||
| function createSelectionUI() { | ||
| if (selectionUI) return selectionUI; | ||
|
|
||
| const { div, button } = van.tags; | ||
| selectionUI = div( | ||
| { | ||
| id: 'text-selection-ui', | ||
| style: | ||
| 'position: fixed; background: color-mix(in srgb, var(--theme-surface), transparent 10%); border-radius: 8px; padding: 8px; z-index: 100000; opacity: 0; box-shadow: 0 4px 12px rgba(0,0,0,0.25); transition: opacity 150ms', | ||
| }, | ||
| button( | ||
| { | ||
| style: | ||
| 'background: var(--theme-secondary); color: var(--theme-onSecondary); padding: 6px 12px; margin: 2px; border-radius: 4px; font-size: 12px;', | ||
| onclick: e => { | ||
| if (reader.hidden.val) { | ||
| e.stopPropagation(); | ||
| } | ||
| removeSelectedText(); | ||
| }, | ||
| }, | ||
| 'Remove', | ||
| ), | ||
| button( | ||
| { | ||
| style: | ||
| 'background: var(--theme-primary); color: var(--theme-onPrimary); padding: 6px 12px; margin: 2px; border-radius: 4px; font-size: 12px;', | ||
| onclick: e => { | ||
| if (reader.hidden.val) { | ||
| e.stopPropagation(); | ||
| } | ||
| replaceSelectedText(); | ||
| }, | ||
| }, | ||
| 'Replace', | ||
| ), | ||
| ); | ||
|
|
||
| document.body.appendChild(selectionUI); | ||
| return selectionUI; | ||
| } | ||
|
|
||
| function showSelectionUI() { | ||
| const ui = createSelectionUI(); | ||
|
|
||
| // Get selection bounds | ||
| const selection = window.getSelection(); | ||
| if (selection.rangeCount > 0) { | ||
| const range = selection.getRangeAt(0); | ||
| const rect = range.getBoundingClientRect(); | ||
|
|
||
| // Get UI element heights from CSS variables (with fallbacks) | ||
| const statusBarHeight = | ||
| parseInt( | ||
| getComputedStyle(document.documentElement).getPropertyValue( | ||
| '--StatusBar-currentHeight', | ||
| ), | ||
| 10, | ||
| ) || 24; | ||
| const navigationBarHeight = | ||
| parseInt( | ||
| getComputedStyle(document.documentElement).getPropertyValue( | ||
| '--bottom-inset', | ||
| ), | ||
| 10, | ||
| ) || 24; | ||
| const readerPadding = | ||
| parseInt( | ||
| getComputedStyle(document.documentElement).getPropertyValue( | ||
| '--readerSettings-padding', | ||
| ), | ||
| 10, | ||
| ) || 16; | ||
| const uiHeight = 50; // Approximate height of our UI | ||
|
|
||
| // Calculate available space | ||
| const viewportHeight = window.innerHeight; | ||
| const selectionCenterY = rect.top + rect.height / 2; | ||
| const topSafeArea = statusBarHeight + readerPadding + 10; | ||
| const bottomSafeArea = readerPadding + uiHeight + navigationBarHeight; | ||
|
|
||
| // Position UI based on selection location | ||
| let topPosition; | ||
| if (selectionCenterY < viewportHeight / 2) { | ||
| // Selection is in top half, position UI at bottom | ||
| //TODO: make this dynamic | ||
| const avoidScrollbar = reader.generalSettings.val.verticalSeekbar | ||
| ? 0 | ||
| : 42; | ||
| const avoidUI = !reader.hidden.val ? 46 + avoidScrollbar : 0; | ||
| topPosition = viewportHeight - bottomSafeArea - avoidUI - 4; | ||
| ui.style.top = topPosition + 'px'; | ||
| ui.style.bottom = 'auto'; | ||
| } else { | ||
| // Selection is in bottom half, position UI at top (accounting for status bar) | ||
| topPosition = Math.max(topSafeArea, statusBarHeight + 20); | ||
| const avoidUI = !reader.hidden.val ? 34 : 0; | ||
| ui.style.top = topPosition + avoidUI + 'px'; | ||
| ui.style.bottom = 'auto'; | ||
| } | ||
|
|
||
| // Center horizontally | ||
| ui.style.left = '50%'; | ||
| ui.style.transform = 'translateX(-50%)'; | ||
| } else { | ||
| // Fallback: position at top if no selection rect available | ||
| ui.style.top = '20px'; | ||
| ui.style.left = '50%'; | ||
| ui.style.transform = 'translateX(-50%)'; | ||
| ui.style.bottom = 'auto'; | ||
| } | ||
|
|
||
| ui.style.opacity = '1'; | ||
| isUIActive = true; | ||
| } | ||
|
|
||
| function hideSelectionUI() { | ||
| if (selectionUI) { | ||
| selectionUI.style.opacity = '0'; | ||
| } | ||
| isUIActive = false; | ||
| } | ||
|
|
||
| function getSelectedText() { | ||
| const selection = window.getSelection(); | ||
| if (selection.rangeCount > 0) { | ||
| return selection.toString().trim(); | ||
| } | ||
| return ''; | ||
| } | ||
|
|
||
| function removeSelectedText() { | ||
| const selectedText = getSelectedText(); | ||
| if (selectedText) { | ||
| reader.post({ | ||
| type: 'text-action', | ||
| data: { remove: selectedText }, | ||
| }); | ||
| } | ||
| hideSelectionUI(); | ||
| window.getSelection().removeAllRanges(); | ||
| } | ||
|
|
||
| function replaceSelectedText() { | ||
| const selectedText = getSelectedText(); | ||
| if (selectedText) { | ||
| // For replace, we need user input, so send a different message | ||
| reader.post({ | ||
| type: 'text-action', | ||
| data: { replace: selectedText }, | ||
| }); | ||
| } | ||
| hideSelectionUI(); | ||
| window.getSelection().removeAllRanges(); | ||
| } | ||
|
|
||
| // Handle text selection | ||
| document.addEventListener('selectionchange', function () { | ||
| const selectedText = getSelectedText(); | ||
| if (selectedText) { | ||
| showSelectionUI(); | ||
| } else if (!isUIActive) { | ||
| hideSelectionUI(); | ||
| } | ||
| }); | ||
|
|
||
| // Hide UI when clicking/tapping elsewhere | ||
| document.addEventListener('touchstart', function (e) { | ||
| if (isUIActive && selectionUI && !selectionUI.contains(e.target)) { | ||
| const selectedText = getSelectedText(); | ||
| if (!selectedText) { | ||
| hideSelectionUI(); | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| document.addEventListener('click', function (e) { | ||
| if (isUIActive && selectionUI && !selectionUI.contains(e.target)) { | ||
| const selectedText = getSelectedText(); | ||
| if (!selectedText) { | ||
| hideSelectionUI(); | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| // Hide UI on scroll | ||
| window.addEventListener('scroll', function () { | ||
| hideSelectionUI(); | ||
| }); | ||
| })(); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.