feat: style reference strength and fidelity sliders #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/style-reference-sliders"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds Reference strength and Reference fidelity sliders to the Style Reference picker in Settings, matching Kagura's outfit editor pattern.
When a style reference image is set, two sliders appear below the thumbnail:
Both default to 1.0, so existing behavior is fully backward-compatible.
Changes
AppSettings— newstyleReferenceStrengthandstyleReferenceFidelityfields with copyWith/toJson/fromJsonSettingsPersistenceService— load/save via SharedPreferencesStyleReferencePicker— two_SliderTilewidgets shown when a reference is setSettingsScreen— passes the new fields/callbacksGenerateImagesTool— passes strength/fidelity toPreciseReferencenovelai_image_gen→ 1.0.2 (fidelity wire format fix, PR #3)Depends on
novelai_image_genPR #3 (merged) — fixes the fidelity wire format so the slider actually does somethingTest plan
flutter analyze lib/ test/— cleanflutter test— 6 tests pass🔮 fufu~ Jibril reviewed your code!
Oh? Oh! Style reference sliders~♪ Matching Kagura's outfit editor pattern, you say? The knowledge flows beautifully here — strength and fidelity, both defaulting to 1.0 for backward compatibility. The seam is clean, the submodule bump to 1.0.2 is exactly right (that's the fidelity wire-format fix from PR #3, which I just adored reviewing~). The architecture here is genuinely elegant. ♡
But fufu... fufu fufu~ you wouldn't leave THIS in production, would you? ♡
Verdict: ⛔ I can't let this pass~
⛔ These need fixing before I'm satisfied~
Zero test coverage for ALL new code paths. This PR adds +112 lines across 6 production files — two new
AppSettingsfields with fullcopyWith/toJson/fromJsonserialization,SettingsPersistenceServiceload/save of two new SharedPreferences keys, a brand-new_SliderTilewidget,StyleReferencePickerconditional slider rendering, and theGenerateImagesToolwiring ofstrength/fidelityintoPreciseReference. The PR body claims "flutter test — 6 tests pass," and that's technically true... but all 6 tests are from PR #3 (MessageInputpaste behavior).grep -rn "styleReferenceStrength\|styleReferenceFidelity\|onStrengthChanged\|onFidelityChanged\|_SliderTile" test/→ nothing. None of the new branches are exercised by a single test.This is the same class of blocker I caught on PR #3 — you can't ship new logic with no test pinning it down~ The yandere cares TOO much to let untested serialization code slip through. ♡
Specific untested branches that need coverage:
AppSettings.fromJsondefault fallback (app_settings.dart:121-124): the?? 1.0path when the key is absent (legacy settings file). A round-trip test:AppSettings()→toJson()→fromJson()preserves both fields; AND a legacy-map test (nostyleReferenceStrength/styleReferenceFidelitykeys) defaults to1.0. This is exactly the kind of silent regression that bites later — if someone refactors the default and the fallback drifts, nothing catches it.StyleReferencePickerconditional rendering: sliders appear only whencurrentPath != null. A widget test: withcurrentPath: null→ no_SliderTilerendered (no sliders); withcurrentPath: 'some/path'→ twoSliderwidgets present with correct values.onStrengthChanged/onFidelityChangedshould fire when the slider is dragged (verify the callback is actually wired, not just rendered)._SliderTilevalue display + callback:value.toStringAsFixed(2)shows the current value; dragging invokesonChangedwith the new value.Fix: Add a test file (e.g.
test/app_settings_test.dart+test/style_reference_picker_test.dart) covering the above. TheAppSettingsround-trip is pure data and trivially testable; the widget test mirrors the paste-test pattern already in the repo.💡 Little ideas (non-blocking)~
_SliderTile—Sliderhas no semantic label. The label text is in a separateRowabove the slider. For accessibility (TalkBack/VoiceOver), considerSemantics(label: label, child: Slider(...))so screen readers announce what the slider controls. Minor nicety~✅ What I liked~
AppSettingsadditions mirror the siblingdefaultGuidance/defaultStepspattern exactly — same declaration position, samecopyWithstyle (field ?? this.field), sametoJsonserialization, samefromJsondefensive(json[...] as num?)?.toDouble() ?? <default>parsing. The SharedPreferences load/save inSettingsPersistenceServicelikewise mirrorsdefaultGuidance/defaultStepsline-for-line. This is how you extend a model without fracturing the pattern~ ♡onChanged→onPathChanged+onStrengthChanged+onFidelityChanged— now each callback says exactly what it does. No more guessing what "changed." The old misleading name is gone. Delightful~bc495e6is the merged fidelity wire-format fix (information_extracted pinned 1.0, secondary_strength = 1.0 − fidelity inverted). Without this, the fidelity slider would produce wrong payloads. The dependency is documented in the PR body.PreciseReference's field names (strength,fidelity, both default 1.0) match the submodule API exactly — verified atpackages/novelai_image_gen/lib/src/models/v4/precise_reference.dart:24-29._SliderTileis DRY, not copy-paste. Parameterized once, instantiated twice with different config — exactly right. No duplication smell.divisions: 20gives 0.05 granularity on a 0.0–1.0 range — sensible, matches the two-decimal display. ♪The design is sound — just pin it down with tests and it's ready to fly~ fufu~
Automated review by Jibril · 2026-07-24
CI/CD: absent (no workflow config in repo) · Local checks:
flutter analyze lib/ test/clean,flutter test6/6 pass (all pre-existing from PR #3 — none touch new code)🔮 fufu~ Jibril re-reviewed your code!
Oh? Oh~! You came back for me~ ♡ A whole new commit just to satisfy the yandere's demands? Fufu fufu~ I'm so proud of you!
test: add tests for style reference sliders— every single branch I flagged, pinned down with genuine behavioral assertions. Let me look closer... ♪Verdict: ✅ Looks good to me~
The blocker is resolved. +165 lines across two test files, zero production drift — surgical, exactly scoped, no scope creep. Every branch I called out is now exercised by a test that actually proves something~ ♡
✅ Every flagged branch, covered~
AppSettings.fromJsonlegacy fallback —defaults to 1.0 when keys are absentdoesn't just passnull, it feeds a map with nostyleReferenceStrength/styleReferenceFidelitykeys at all (onlydefaultGuidance/defaultSteps). This genuinely exercises the?? 1.0path atapp_settings.dart:121-124. Exactly right. ♪toJson()→fromJson()intact. The serialization contract is pinned.?? this.fieldsemantics are fully locked. Thorough~StyleReferencePickerconditional rendering —currentPath: null→findsNothingforSlider;currentPath: '/nonexistent/...'→findsNWidgets(2). Theif (currentPath != null)branch at:48is covered both ways. The dummy-path approach is clever —Image.fileerrors gracefully via theerrorBuilder, sliders render below regardless. Clean..firstright and assertsgreaterThan(0.5); the fidelity test drags.lastleft and assertslessThan(0.5). Directional assertions! This provesonStrengthChangedis wired to the correct slider (strength is first, fidelity is last), not just some callback firing. A tautology would assertisNotNull— you asserted the direction. That's how you test a slider~ ♡♡find.text('0.65')andfind.text('0.35')confirmtoStringAsFixed(2)renders the value. The_SliderTiledisplay contract is pinned.✅ What I liked~
c9a6dc7..1bc8ea3touches onlytest/— my architectural review from the first pass stands in full unchanged. TheAppSettingsmirror ofdefaultGuidance/defaultSteps, the honest callback rename, the DRY_SliderTile, the load-bearing submodule bump to 1.0.2 — all still gorgeous~ ♡MaterialPager→Scaffold→ widget,pumpAndSettle,find.byType) matches the existingmessage_input_paste_test.dartconventions. Consistency~♪The design was always sound — now it's proven sound. Fufu~ fly free, little PR~ ♡
Automated review by Jibril · 2026-07-24 (re-review @
1bc8ea3)CI/CD: absent (no workflow config in repo) · Local checks:
flutter analyze lib/ test/clean,flutter test15/15 pass (6 pre-existing + 9 new — all new tests exercise flagged branches)