some chores and bug fixes regarding widgets, shared components, and scroll wheel - #561
Merged
Merged
Conversation
…s, since the widget config is its only caller and the file sat among the settings components while naming the shared one, and end it with a newline
…, so applying or cancelling a custom widget colour reads the same as saving or cancelling anywhere else in the app rather than as a pair of flat labels
…ce the time size alone offers eighteen values and a dropdown hung off a chip made the reader scroll a popup to reach the ends of a range The wheel picks by position in the size list rather than by the value itself, so the sizes stay the curated list the widget already exposes and the picker gains a label for turning a position into the text it shows.
…puted a different way, so the last value of a picker that starts above zero saves as itself instead of as zero The picker labelled each page as its position within the range plus the starting offset but reported the offset added before the wrap, which agreed everywhere except the final page. A snooze or alarm timeout scrolled to 120 minutes therefore displayed 120 and stored 0. The twelve hour alarm picker escaped it only because its meridiem mapping turns a stray zero into the same hour as twelve.
… runs past ninety nine stops padding its small numbers to two digits while leaving its large ones at three A duration counts minutes rather than naming a position in a clock, so nothing is owed to a fixed width. The clock and timer wheels keep their padding, where a lone digit beside another would read as the wrong time.
…g names its value where every other setting in the app does instead of parking it in a button off to the right
…reen without keeping the changes is a button the way it is in the alarm editor rather than a guess at the back gesture Cancelling finishes the activity, which already carries the cancelled result it set on the way in, so a widget being placed for the first time is still dropped and one being edited keeps what it had.
…aded, so the two colour rows carry an icon and a title of the same weight instead of a bare line of body text starting further left than its neighbours
…ens the app, since the provider was wiring a tap of its own that the options then tried to replace Both text clock widgets already set or clear the tap themselves according to the open on click setting, and a pending intent that only differs by its launch flags is the same pending intent to the system, so the provider's flagless one survived and the options' request to clear the task never took effect.
…the task is not answered with the pending intent a running timer's notification made first Every widget asked for request code zero against a plain intent for the main activity, which is the same request the timer service makes for its notification, and the system hands back whichever of them was built first along with the launch flags it was built with. Keying the request on the widget being drawn keeps them apart.
… saving the face redrew the widget from views that had never been given one The tap was wired where the widget is updated by the system but not where it is updated after configuring it, and configuring is the first thing that happens to a widget being placed, so an analog clock has never opened the app from the moment it was added.
…already configured, so a widget whose configuration was cancelled can still be opened and finished from the widget settings A widget added without saving its configuration has no stored settings, and the list read that as the widget not existing, which left the one case that most needs editing as the one case with no way to reach it. Loading it at its defaults shows it as it is drawn. The set of widget ids to ignore went with it, since nothing ever added an id to that set.
…get whose configuration is never saved still keeps time and opens the app rather than only looking as though it does A widget host draws the provider's own layout while it waits for a configuration, and that layout carries clocks that tick on their own, so a placed widget looks finished long before the app has drawn it once. Nothing is wired to it until the app does, which left a widget whose configuration was cancelled ticking correctly and ignoring every tap. Writing the defaults on the way in settles it, and cancelling still discards whatever was changed on the screen itself.
…the shadow reads like the vibration pattern it resembles rather than a card of its own with the choice folded away behind an expander The setting was a card built for itself alone, animating its corners between two radii, rotating a chevron and hiding the five styles behind advanced settings, none of which appears anywhere else in the app. A switch that names the current style and opens a picker says the same thing in the shape every other choice of its kind already takes, and the styles say their own names now rather than carrying English in the enum where no translation can reach them. The step slider the card drew went with it, since nothing else ever drew one.
…configured, so setting up a vertical clock stops calling itself a digital clock The screen is shared by both text clock widgets and titled itself with the digital one for either of them, since the title was written into the shared activity rather than asked of the widget that opened it.
…nge, so the three settings that describe its date sit together instead of once each among the switches, the sizes and the colours The screen listed ten settings in the order they were written, which put showing the date at the top, its size five rows down and its colour two rows after that, and asked the reader to hold the whole list in mind to configure one half of a clock. General keeps what belongs to the widget itself, and Time and Date each keep the whole of their own.
…s left without saving, and go on discarding the changes when a widget already configured is left the same way A host asks the configuration screen whether to keep the widget it is holding, and the screen answered no for every way out but the save button, so leaving the first configuration told the host to throw the widget away. It is the placement being answered the first time and only the changes on the screen every time after, so the first says yes at its defaults and the rest still say no.
…ngth, an alarm timeout or a widget text size alone is a button rather than a tap outside the dialog Every one of them already dropped the scrolled value when dismissed, but said so only by having no way to agree, which asked the reader to know that tapping away was safe.
…e dialog, since the three were the same wheel between the same two buttons written out twice The minutes dialog and the size dialog had already converged on a title, a wheel, a unit beside it and save against cancel, and adding the cancel button meant writing the same pair into both. The shared one takes the range and the words rather than assuming minutes, so a duration passes the minutes it counts and a text size passes positions in the sizes it offers.
…aw, so the unit beside a widget text size stops stepping aside when the sizes reach three digits The width was reserved by asking how high the wheel counts, which answered for the wheel that counts the minutes it shows but not for the one that counts positions in a list of sizes and draws the size at each. Asking the labels themselves answers for both, and answers the same as before everywhere the two questions agreed.
…and end it with cancel beside save, so all three widgets are set up on a screen that says the same things in the same places The screen called itself after the one choice it offers rather than the widget it configures, and offered only a way to agree, while the two text clock widgets already named themselves and answered both ways.
…de it do, so the one column of the alarm picker that was left on the default fling stops behaving unlike the two it sits next to The commit that centred the snap and made the highlighted value the selected one gave the shared wheel a fling that may travel the whole range and gave this one only the centred snap, so it kept the default that settles within a page of where it started.
…go leaves the value that was highlighted rather than the one the page scrolled back to The alarm is the only screen where these wheels sit on a page that scrolls the way they do, and nothing said which of the two a drag belonged to, so the page took a share of it often enough that a wheel could settle back where it started. The timer and the dialogs never had to answer this because nothing behind their wheels moves.
…ry part of this picker is called what the rest of them are called The wheel is a scroll time picker, the alarm's row of them a scroll alarm time picker and the dialog around one a scroll picker dialog, while the timer's row alone was a dial, which is the one thing none of them draw.
…e picker built for those two was the shared wheel written out a second time It kept its own pager over two pages, its own centred snap, its own haptic tick and its own highlight, all of which the shared wheel already does, and the numbers agreed exactly: a wheel of two values starting at the chosen one lands on the same page from either. Naming the two values is all the wheel needed to be told.
…num it came to sit above does not use the API it opts into
…arts, since it picks one value of anything rather than a time and the timer is only one of the four places that draw it Everything built out of it is a picker, being what a reader picks a time or a length or a size with, while this is the column those pickers are made of, and the app already calls this style a wheel where it offers it. It sat in the timer's own folder from when the timer was its only caller, which left the alarm, the widget settings and the dialog reaching across a feature they have nothing to do with.
…ing picker style what it does, so the widget list stops offering two clock faces for different widgets and the style beside Clock stops sounding round as well The digital and analog widgets both carried a clock face, which named the analog one and said nothing about the other, while the vertical widget already showed the stacked cards it draws, so a single card says the same thing for the digital one. The scrolling style sat next to the clock style under the same heading while calling itself a wheel, which is the shape of the option beside it rather than the one it offers.
…een no longer shows, since a translation without a string to translate is flagged as an extra one The screen names the widget it configures now, so the twenty seven locales that had translated its old title are left holding a string nothing asks for.
…reens name their widget the way a title names a thing rather than the way a sentence starts
…ow dialog be answered rather than answered by touching an option The picker dialogs the app already had name the thing they select, while the ones the widget settings opened were titled after the setting behind them or after the colour model they happen to use, so a custom colour, a date size and a time size now say they are being selected the way a snooze length and a vibration pattern do. The shadow dialog applied a style the moment one was touched, which read as a menu rather than a choice and left its cancel button with nothing to cancel. It holds the touched style now and applies it on save, beside a cancel that leaves the widget as it was.
…ch one it uses, and label the shadow style as a style The time zone row explained what turning it on would do and went on explaining it after a zone had been chosen, so the one thing it could usefully say, which zone the widget follows, was the one thing it never did. It says the zone once there is one, and keeps the explanation for when there is not. The shadow row named a style without saying it was one, which reads oddly beside a preset called Off.
…the line under each widget was written into the screen rather than into the strings The three lines it can show were spelled out in English where no translation could reach them, and named a time zone in a different case and a different spelling from the setting that chooses one.
…ur dialog after the colour it picks, so the widget settings open dialogs the app owns rather than dialogs written into the screen The list of styles was written into the settings screen, and the colour dialog was named after the three sliders it happens to use and agreed to a colour with Apply while everything else in the app agrees with Save. Both are components now, beside the scrolling one, and both answer with save against cancel.
…to rather than the one it was scrolled from A release too slow to fling is decided by how far the page was dragged against a threshold, which was half a row, so a drag that had already moved the highlight could still be read as not far enough and settle back where it began. A fifth of a row settles forward instead, which is the value the reader was looking at when they let go.
… left it, while letting a flick coast as far as it ever did Where a release lands was decided entirely from how fast and how far the finger moved, and a slow flick can work out a resting place a row behind the one under the highlight, which is the value the reader is looking at and the one they mean. The resting place is now held to that row at the least, so a flick still travels the whole range and a release never hands back the row it came from. The threshold that decides a release with no flick in it goes back to half a row, since it agrees with where the highlight moves, and biasing it lower only traded one wrong row for another.
…el, so a release settles where it is instead of coasting a row back and being pulled forward again Holding the resting place to the highlighted row fixed which value a release chooses but not what it looks like getting there, because a wheel coasts on the speed it was let go with before it settles anywhere, and a finger that slows to a stop often leaves pointing back the way it came. That coast ran a row backwards and the resting place then pulled it forward, which reads as the wheel choosing wrongly and correcting itself. A release whose speed points against the way the wheel was just turned is treated as no speed at all, so there is nothing to coast backwards and the wheel simply settles. A release that keeps going the way it was turned still carries every bit of its speed.
…k to coast as it always did A wheel worked out where to come to rest from how fast and how far the finger moved, which is the right question for a flick and the wrong one for a drag. Someone dragging a wheel a row at a time is reading it, and the row they stop on is the answer they mean, whatever the numbers behind the gesture work out to. A release too slow to be a flick now carries no speed at all and the wheel simply settles on the row it is showing. A flick still carries its speed and lands wherever it lands, which is all a flick is asked to do.
Collaborator
|
tysm :) |
Elektron123
added a commit
that referenced
this pull request
Aug 21, 2026
remove orphaned translations left after #561
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
#557 added the widget manager and the RGB colour picker. while going through it on my phone I found the widgets don't actually open the app properly if you place the widget but don't save (by pressing back), so this started as three bug fixes and grew into a pass over the widget settings screen and the wheel pickers it borrows.
Bug 1: Opening the app through the widget
tapping a widget opens a second copy of the app on top of the first, so you press back twice to leave.
TextWidgetProviderwires a tap on every update, thenapplyDigitalClockWidgetOptionswires another over it withFLAG_ACTIVITY_CLEAR_TASK. two pending intents that differ only by their launch flags are the same pending intent as far asfilterEqualsis concerned, soFLAG_UPDATE_CURRENThands back the first one and the clear-task flags never apply.MainActivityisstandard, so the second copy stacks.the provider no longer wires a tap at all, since both text clock widgets already set or clear it themselves from the open-on-click setting.
the analog widget on the other hand never opened the app at all. its tap is wired in
onUpdate, butupdateAnalogClockWidgetbuilds freshRemoteViewswithout one and pushes them, and that runs the moment you pick a clock face. the tap moved intoapplyAnalogClockWidgetOptions, which both paths call.Bug 2: Widget initialization issue
the first configuration screen upon placing the widget answers the host's "do I keep this widget?", and it answered no for every exit (pressing back or pressing cancel) except Save. so backing out of a first placement told the host to throw the widget away, while my launcher (vivo) kept drawing it anyway, so I have a widget placed but the state remains uninitialized. the widget looks fine because the host draws the provider's own layout, which is full of
TextClockviews that tick on their own, but nothing is wired to it and it ignores every tap, which wouldn't allow me to edit the widget or open the app through the widget anymore, so I have to simply remove the widget and create a new one and actually press "save" to first initialize it properly.to fix this, first time placement now answers yes at its defaults. this also directly fixes the newly widget list not listing uninitialized widgets.
Standardization 1: Widget settings page
I'm sorry but the widget setting page is like its own thing, it doesn't follow the standard of the rest of the app conventions at all. The settings are now sectioned under General, Time, and Date, the same way #555 grouped the app settings.
apart from that, the text size dropdown was built for this widget settings alone, which is so unnecessary, so I just standardize that to use the scroll picker dialog.
the shared screen also titled itself "Digital clock widget" for the vertical widget, so now they're title cased and separated to "Digital Clock Widget", and "Vertical Clock Widget" in title case, since it's... a title. the analog one is now titled "Analog Clock Widget" to keep consistent with the other 2 widgets' titles.
the text shadow was its own card written into the screen, and the RGB picker was a dialog filed under the settings components while declaring itself a shared one. both are proper shared components now beside the scrolling one, RadioPickerDialog and ColorPickerDialog, which should come in useful later.
ScrollWheelScrollPickerDialogRadioPickerDialogColorPickerDialogthe digital clock shared a clock face icon with the analog one in the list. the list's own subtitles were hardcoded in English in the screen itself, so those are translatable strings now too.
The Scroll Wheel Picker (Bug 3: fix insensitive scroll wheel, which fixes by Standardization 2: standardizing the scroll wheel into a shared component)
two things turned up in the scroll wheel;
the snooze, timeout, and size dialogs are now using the same scroll wheel component instead of written out separately, so this dialog, the
MinutePickerDialogis generalized intoScrollPickerDialogand all three use it, and added a Cancel beside Save in the dialog, for design consistency.the AM/PM column was another scroll wheel written out separately, so it never got the fling fix behaviour #536 gave the others. it's now using the shared component, told to name two values instead of numbers.
the alarm is also the only screen where these wheels sit on a page that scrolls the way they do, and nothing said which of the two a drag belonged to, so the page could take a share and a wheel settle back where it started. a drag that lands on the wheels stays with them now.
I also renamed
ScrollTimePickertoScrollWheeland moved it beside the other shared components, as picker is used to define the layouts on how to use theScrollWheel.TimePickerDialbecameScrollTimerPickerto match. so now the component usage is more clear, like the following:ScrollWheel
the individual scroll wheel column component (now sits under presentation/components/)
ScrollAlarmTimePicker
defines the layout using the
ScrollWheelcomponent for hour + minute + AM/PM, with the 12/24-hour mappingScrollTimerPicker
defines the layout using the
ScrollWheelcomponent for hours + minutes + secondsScrollPickerDialog
defines the layout in a dialog using the
ScrollWheelcomponent for oneScrollWheeland a unitthe picker style option is called "Scroll" instead of "Wheel", because it sits next to "Clock" under the same heading and Clock is the round one.
wheelandnumber_padwere never translated so nothing orphans there, but retitling the analog screen orphansselect_clock_facein 27 locales, which lint flags asExtraTranslation, so I removed those in the same commit.happy to split any of this out if it's easier to review in pieces.
Related PRs
merge this before #556, #556 can wait, I will push a patch (if needed) to #556 after this one is merged in.
it builds on #557, #536, #534 and #542, and follows the sectioning from #555.