-
-
Notifications
You must be signed in to change notification settings - Fork 280
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
Feature/manga scroll width changer #2980
Feature/manga scroll width changer #2980
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, the idea is pretty good but needs a level of polish and testing of course against all the different renderers and how it plays with things like swipe to paginate.
If you're willing to do the work, I'm willing to merge this in for users.
</select> | ||
<input id="page-fitting-slider" type="range" min=0 max=100 class="form-range visually-hidden" formControlName="widthSlider"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're going to need to have a label that's invisible for this. You need "" around your values for attr="value".
@@ -513,6 +513,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { | |||
autoCloseMenu: new FormControl(this.autoCloseMenu), | |||
pageSplitOption: new FormControl(this.pageSplitOption), | |||
fittingOption: new FormControl(this.mangaReaderService.translateScalingOption(this.scalingOption)), | |||
widthSlider: new FormControl(70), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to have this disabled by default.
@@ -549,8 +550,31 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { | |||
takeUntilDestroyed(this.destroyRef) | |||
).subscribe(() => {}); | |||
|
|||
this.generalSettingsForm.get('widthSlider')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { | |||
//update the css width | |||
const styleSheets = document.styleSheets; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't needed. You just need the width value from this. So:
this.widthOverride$ = this.generalSettingsForm.get('widthSlider')?.valueChanges.pipe(
map(val => val < -1 ? 'initial' : val + '%'),
takeUntilDestroyed(this.destroyRef)
);
This would give you back the string value. Then on the image you'd do style={{widthOverride$}}.
But the thing is, the image isn't in this component. It is rendered out in the renderers. So while the control is here, it would need to populate the readerSettings and the above code would need to be in each renderer.
You probably also need to disable the input for double page layout.
|
||
|
||
this.generalSettingsForm.get('fittingOption')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { | ||
let slider = document.getElementById("page-fitting-slider") as HTMLInputElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to do this type of thing in Angular. We should enable/disable only. We shouldn't hide it from the UI.
Also keep the subscribe blocks empty. Put this in a tap() so that subscribe can be empty.
@@ -1,7 +1,8 @@ | |||
export enum FITTING_OPTION { | |||
HEIGHT = 'full-height', | |||
WIDTH = 'full-width', | |||
ORIGINAL = 'original' | |||
ORIGINAL = 'original', | |||
MANUAL = 'manual' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this at all. I think we can just have a slider that applies an arbitrary width with the user is in WIDTH fitting.
I'd love to the work, I will just need a while to make these changes. I will get back to you when they are done |
the last commit changes the feature to only work on the infinite scroll manga-reader for now, while fixing the scrolling issue. Tested on mobile and desktop 2024-06-06.12-25-44.mp4 |
feature now works in all three single page modes (up/down, right/left, infinite scroll) and is disabled/does nothing in everything else, as it has no implementation there Also are we sure we don't want to hide the slider per default and only show it for the supported modes? If yes the feature works on my part, let me know if there is a change that needs to be done |
/** | ||
* Width overwrite for maunal width control | ||
*/ | ||
widthOverride$ : string = 'none'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The $ sign means that the variable is an observable. The idea is to map it to the widthSlider valueChanges and use map to transform it to the style you need.
this.mangaReaderComponent.generalSettingsForm.get("fittingOption")?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { | ||
var img = this.document.getElementById('image-1'); | ||
if(!img) return; | ||
img.style.width = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please always use single quotes in javascript for this project.
else img.style.width = this.widthOverride$; | ||
}); | ||
//reset manual width when fitting option changes | ||
this.mangaReaderComponent.generalSettingsForm.get("fittingOption")?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't how you should code it. Don't pass the parent component into the child. You can get fittingOption from readerSettings$ and if you can't, update the code so it's packed in the ReaderSetting interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so from the mangareader component updating the setting and in the renderers subscribing to the settings value to make changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, see imageFitClass$ in the double-renderer and my comment below.
var scaling = this.mangaReaderComponent.generalSettingsForm.get("fittingOption")?.value; | ||
if (FITTING_OPTION.HEIGHT == scaling) return; | ||
|
||
if(this.widthOverride$ == 'none') img.style.width = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you explain this further? I am not experienced in this area and when I try this like you say I get "cannot assign to 'style' because it is an import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is that in Angular we don't set things on DOM nodes directly, so instead of setting width like this through logic, instead we want to store the width value in an observable (widthOverride$) then in the template, directly use that value like I showed above.
You can see something similar for imageFitClass$.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, as someone normally only doing procedural programming in C++ this whole webdev angular stuff is very confusing to me. Hopefully I get the code to your liking the next time
The logic itself should work fine, even deployed it on my own server.
@@ -194,6 +194,8 @@ | |||
<option value="full-width">{{t('width')}}</option> | |||
<option value="original">{{t('original')}}</option> | |||
</select> | |||
<label for="page-fitting-slider" class="form-label"></label> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Label needs text inside it. I'm open to the label name.
@@ -194,6 +194,8 @@ | |||
<option value="full-width">{{t('width')}}</option> | |||
<option value="original">{{t('original')}}</option> | |||
</select> | |||
<label for="page-fitting-slider" class="form-label"></label> | |||
<input id="page-fitting-slider" type="range" min="-1" max="100" class="form-range" formControlName="widthSlider"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the min of -1 for? Wouldn't 0 mean "none"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still needs a bit of work. Please also test against the double readers. The input needs to be disabled for those modes very likely.
One thing I also just thought about in addition to double page layout having it disabled, canvas renderer (which is used for SplitOptions.LTR/RTL) needs to disable the field as well. So to recap, the field should be disabled whenever: |
Hey, did the rewrite in the style you wanted and this feature is only enabled for, specific combinations: Hope this is more to your liking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pulling this down to give it an actual test as well. Code is looking pretty good, just a few minor things.
this.currentPageElem= this.document.querySelector('img#page-' + this.pageNum); | ||
if(!this.currentPageElem) return | ||
var images = Array.from(document.querySelectorAll('img[id^="page-"]')) as HTMLImageElement[]; | ||
for(let i = 0; i < images.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use newlines after if (...) branch
and before for loops and return statements. Also new line after a closing }
. It helps make reading the code much easier.
this.currentPageElem= this.document.querySelector('img#page-' + this.pageNum); | ||
if(!this.currentPageElem) return | ||
var images = Array.from(document.querySelectorAll('img[id^="page-"]')) as HTMLImageElement[]; | ||
for(let i = 0; i < images.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably just want to use a foreach loop so we don't need var img = images[i];
if(!this.currentPageElem) return | ||
var images = Array.from(document.querySelectorAll('img[id^="page-"]')) as HTMLImageElement[]; | ||
for(let i = 0; i < images.length; i++) { | ||
var img = images[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use var
. Always use let
and const
.
UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.ts
Show resolved
Hide resolved
@@ -194,6 +194,8 @@ | |||
<option value="full-width">{{t('width')}}</option> | |||
<option value="original">{{t('original')}}</option> | |||
</select> | |||
<label for="page-fitting-slider" class="form-label">Manual Width</label> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need localization on the label.
@@ -194,6 +194,8 @@ | |||
<option value="full-width">{{t('width')}}</option> | |||
<option value="original">{{t('original')}}</option> | |||
</select> | |||
<label for="page-fitting-slider" class="form-label">Manual Width</label> | |||
<input id="page-fitting-slider" type="range" min="0" max="100" class="form-range" formControlName="widthSlider"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we shouldn't allow 0. I think range from 1-100 is appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refering to the other comment as well, you suggested to let 0 be the value to turn it off, so if 0 is inputed the default behaviour of the width mode is restored. That is also why it defaults to 0 instead of 100%
UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts
Outdated
Show resolved
Hide resolved
UI/Web/src/assets/langs/en.json
Outdated
@@ -1695,7 +1695,8 @@ | |||
"image-scaling-label": "Image Scaling", | |||
"height": "Height", | |||
"width": "Width", | |||
"manual_width": "Manual Width", | |||
"width_override": "Width Override", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to match the naming scheme of the other localization keys. override-width-label and off should be the keys.
@@ -568,6 +572,13 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { | |||
this.generalSettingsForm.get('widthSlider')?.setValue(0); | |||
this.generalSettingsForm.get('widthSlider')?.disable(); | |||
} | |||
|
|||
this.widthOverrideLabel$ = this.readerSettings$?.pipe( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix indentation
@@ -278,6 +276,13 @@ | |||
min="10" max="100" step="1" formControlName="darkness"> | |||
</div> | |||
|
|||
<div class="col-md-6 col-sm-12"> | |||
<label for="page-fitting-slider" class="form-label">{{t('width_override')}}: | |||
{{ (widthOverrideLabel$ | async) ? (widthOverrideLabel$ | async) : t('width_override_off') }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably re-write this completely as:
@if (widthOverrideLabel$ | async; as widthOverrideLabel) {
{{ widthOverrideLabel ? widthOverrideLabel : t('off') }}
}
<label for="page-fitting-slider" class="form-label">{{t('width_override')}}: | ||
{{ (widthOverrideLabel$ | async) ? (widthOverrideLabel$ | async) : t('width_override_off') }} | ||
</label> | ||
<input id="page-fitting-slider" type="range" min="0" max="100" class="form-range" formControlName="widthSlider"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's rename these ids to be width-override-slider instead
After your last push, I see a few more issues:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more comments then I'm good to merge
@@ -549,9 +554,33 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { | |||
takeUntilDestroyed(this.destroyRef) | |||
).subscribe(() => {}); | |||
|
|||
this.generalSettingsForm.get('pageSplitOption')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { | |||
const fitting = this.generalSettingsForm.get('fittingOption')?.value; | |||
if(PageSplitOption.FitSplit == val && FITTING_OPTION.WIDTH == fitting) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space after if. If (
and also newline above if statements please
@@ -549,9 +554,33 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { | |||
takeUntilDestroyed(this.destroyRef) | |||
).subscribe(() => {}); | |||
|
|||
this.generalSettingsForm.get('pageSplitOption')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move the subscribe into a tap so that subscribe can be empty.
In addition, move each pipe into a new line, like you see elsewhere.
I would also get the control in a variable then re-use in the code, so:
const widthOverrideControl = this.generalSettingsForm.get('widthSlider')!;
@@ -549,9 +554,33 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { | |||
takeUntilDestroyed(this.destroyRef) | |||
).subscribe(() => {}); | |||
|
|||
this.generalSettingsForm.get('pageSplitOption')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { | |||
const fitting = this.generalSettingsForm.get('fittingOption')?.value; | |||
if(PageSplitOption.FitSplit == val && FITTING_OPTION.WIDTH == fitting) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a bit of documentation about our decisions about when this should work. It will likely help me in the future when there is a bug.
@@ -53,6 +53,11 @@ export class SingleRendererComponent implements OnInit, ImageRenderer { | |||
pageNum: number = 0; | |||
maxPages: number = 1; | |||
|
|||
/** | |||
* Width overwrite for maunal width control |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Width override*
did these changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I'll merge this in and get feedback from nightly users. Appreciate the work.
Added
the ability to change the width of manga pages (video 1)
current bugs with this: changing the width scrolls the pages due to the canvas size changing (video 2)
2024-06-05.17-52-04.mp4
2024-06-05.17-52-51.mp4