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
46
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
46 commits
Select commit
Hold shift + click to select a range
8f33143
copied old code
CD-Z 54737de
clean up WebVieweReader
CD-Z 34db2c6
update pnpm-lock.yaml
CD-Z ab47426
Update index.tsx
CD-Z cf5ada0
Improve TextInput focus and keyboard behavior
CD-Z 7d263e7
optimized app bar animation
CD-Z 6c49696
Remove gap between keyboard and content
CD-Z 785cdc0
Update ToggleButton
CD-Z f33313f
Remove AdvancedTab from Reader settings
CD-Z 2460bac
added code migration
CD-Z 0d0aa6b
Update settings webview
CD-Z bb2f94e
updated text remover modal
CD-Z 9b1d492
small fixes
CD-Z bc1cb67
add stopPropagation
CD-Z c6d8e49
dismiss Keyboard on closing KeyboardAvoidingModal
CD-Z 93c2bdd
add simple regex validation
CD-Z 4cf29ee
Update KeyboardAvoidingModal.tsx
CD-Z 2ca43ae
added localization
CD-Z b86e43d
Update useTextModifications.ts
CD-Z 9672a04
Update useTextModifications.ts
CD-Z 92cbbd1
updated KeyboardAvoidingModal
CD-Z 607a79c
Update SettingsReaderWebView.tsx
CD-Z 806a0b8
Update useTextModifications.ts
CD-Z 822ffde
Update SettingsReaderWebView.tsx
CD-Z 8cf71ea
Update ReaderScreen.tsx
CD-Z 2f6ed73
Update setting migration
CD-Z 93c298d
clone snippets on save
CD-Z 297feb8
fade out disabled ToggleButton
CD-Z f77c8eb
small fixes
CD-Z 18ef214
Custom code screen rework
CD-Z fd0cad8
Switch to KeyboardAwareScrollView
CD-Z 400f8ad
Fix scrolling.
CD-Z 6c78580
redesign
CD-Z 7cb5974
Extracted Snippet
CD-Z cc52d26
update KeyboardAvoidingModal
CD-Z 4d51074
Update CustomCodeScreen with SimpleCodeEditor
CD-Z 7d519c6
added file import
CD-Z ee214d1
rewrite again
CD-Z bb8b8ce
updated codeeditor
CD-Z a98d835
fix item list height calculation
CD-Z e610de7
change to prism for highlighting
CD-Z 7f13993
change highlightColors in Dark mode
CD-Z 7291146
continue on empty text
CD-Z 8f03941
fix smaller issues
CD-Z 0473d91
improved types
CD-Z 55f64fa
Localized new strings
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
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.