Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 0 additions & 24 deletions .claude/settings.local.json

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
CLAUDE.md
.claude/
26 changes: 13 additions & 13 deletions docs/images/action-flow.drawio
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,55 @@
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="2" parent="1" style="text;html=1;fontSize=18;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" value="Action Flow — ActionLocker &amp; LoadingTrackable" vertex="1">
<mxCell id="2" parent="1" style="text;html=1;fontSize=24;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" value="Action Flow — ActionLocker &amp; LoadingTrackable" vertex="1">
<mxGeometry height="36" width="600" x="79" y="-65" as="geometry" />
</mxCell>
<mxCell id="3" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;fontSize=12;fontStyle=1;" value="View dispatches&#xa;receive(action:)" vertex="1">
<mxCell id="3" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;fontSize=16;fontStyle=1;" value="View dispatches&#xa;receive(action:)" vertex="1">
<mxGeometry height="60" width="150" x="40" y="80" as="geometry" />
</mxCell>
<mxCell id="4" edge="1" parent="1" source="3" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#666666;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" target="5" value="">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="5" parent="1" style="rhombus;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;strokeWidth=2;fontSize=11;fontStyle=1;" value="ActionLocker&#xa;canExecute(action)?" vertex="1">
<mxCell id="5" parent="1" style="rhombus;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;strokeWidth=2;fontSize=14;fontStyle=1;" value="ActionLocker&#xa;canExecute(action)?" vertex="1">
<mxGeometry height="90" width="160" x="230" y="65" as="geometry" />
</mxCell>
<mxCell id="6" edge="1" parent="1" source="5" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#b85450;exitX=0.5;exitY=0;entryX=0.5;entryY=1;" target="7" value="">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="7" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#CCCCCC;strokeWidth=1;fontSize=10;fontStyle=2;fontColor=#999999;" value="false → return&#xa;(duplicate blocked)" vertex="1">
<mxCell id="7" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#CCCCCC;strokeWidth=1;fontSize=13;fontStyle=2;fontColor=#999999;" value="false → return&#xa;(duplicate blocked)" vertex="1">
<mxGeometry height="50" width="116" x="252" y="-14" as="geometry" />
</mxCell>
<mxCell id="8" edge="1" parent="1" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#82b366;exitX=1;exitY=0.5;entryX=0;entryY=0.5;fontStyle=2;fontSize=18;fontColor=#82b366;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;labelBackgroundColor=none;" value="true">
<mxCell id="8" edge="1" parent="1" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#82b366;exitX=1;exitY=0.5;entryX=0;entryY=0.5;fontStyle=2;fontSize=24;fontColor=#82b366;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;labelBackgroundColor=none;" value="true">
<mxGeometry relative="1" x="0.05" y="-15" as="geometry">
<mxPoint as="offset" />
<mxPoint x="390" y="110" as="sourcePoint" />
<mxPoint x="430" y="110" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="9" parent="1" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;fontSize=11;fontStyle=1;" value="canTrackLoading?" vertex="1">
<mxCell id="9" parent="1" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;fontSize=14;fontStyle=1;" value="canTrackLoading?" vertex="1">
<mxGeometry height="80" width="140" x="430" y="70" as="geometry" />
</mxCell>
<mxCell id="10" edge="1" parent="1" source="9" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#d6b656;exitX=1;exitY=0.5;entryX=0;entryY=0.5;fontStyle=2;fontSize=16;fontColor=#d6b656;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;labelBackgroundColor=none;" target="11" value="true">
<mxCell id="10" edge="1" parent="1" source="9" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#d6b656;exitX=1;exitY=0.5;entryX=0;entryY=0.5;fontStyle=2;fontSize=20;fontColor=#d6b656;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;labelBackgroundColor=none;" target="11" value="true">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="11" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;fontSize=11;fontStyle=1;" value="loadingStarted()&#xa;counter++" vertex="1">
<mxCell id="11" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;fontSize=14;fontStyle=1;" value="loadingStarted()&#xa;counter++" vertex="1">
<mxGeometry height="50" width="140" x="612" y="85" as="geometry" />
</mxCell>
<mxCell id="12" edge="1" parent="1" source="9" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#999999;dashed=1;exitX=0.5;exitY=1;entryX=0;entryY=0;fontStyle=2;fontSize=15;fontColor=#999999;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;labelBackgroundColor=none;" target="14" value="false">
<mxCell id="12" edge="1" parent="1" source="9" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#999999;dashed=1;exitX=0.5;exitY=1;entryX=0;entryY=0;fontStyle=2;fontSize=20;fontColor=#999999;labelPosition=center;verticalLabelPosition=bottom;align=center;verticalAlign=top;labelBackgroundColor=none;" target="14" value="false">
<mxGeometry relative="1" x="-0.7086" y="-20" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="13" edge="1" parent="1" source="11" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#666666;exitX=0.5;exitY=1;entryX=1;entryY=0;" target="14" value="">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="14" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;fontSize=12;fontStyle=1;" value="Execute action&#xa;(async do/catch)" vertex="1">
<mxCell id="14" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;fontSize=16;fontStyle=1;" value="Execute action&#xa;(async do/catch)" vertex="1">
<mxGeometry height="53" width="160" x="517" y="204" as="geometry" />
</mxCell>
<mxCell id="15" edge="1" parent="1" source="14" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#666666;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" target="16" value="">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="16" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;fontSize=11;" value="Success:&#xa;update state" vertex="1">
<mxCell id="16" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;fontSize=14;" value="Success:&#xa;update state" vertex="1">
<mxGeometry height="46" width="140" x="280" y="190" as="geometry" />
</mxCell>
<mxCell id="25" edge="1" parent="1" source="14" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#b85450;exitX=0;exitY=0.5;entryX=1;entryY=0.5;exitDx=0;exitDy=0;entryDx=0;entryDy=0;" target="17" value="">
Expand All @@ -61,7 +61,7 @@
<mxPoint x="420" y="296" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="17" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;strokeWidth=2;fontSize=11;" value="Error:&#xa;showError()" vertex="1">
<mxCell id="17" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;strokeWidth=2;fontSize=14;" value="Error:&#xa;showError()" vertex="1">
<mxGeometry height="46" width="140" x="280" y="260" as="geometry" />
</mxCell>
<mxCell id="18" edge="1" parent="1" source="16" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#666666;exitX=0;exitY=0.5;entryX=1;entryY=0.25;" target="20" value="">
Expand All @@ -70,7 +70,7 @@
<mxCell id="19" edge="1" parent="1" source="17" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#666666;exitX=0;exitY=0.5;entryX=1;entryY=0.75;" target="20" value="">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="20" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;fontSize=11;fontStyle=1;" value="unlock(action)&#xa;loadingFinished()&#xa;counter--" vertex="1">
<mxCell id="20" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;fontSize=14;fontStyle=1;" value="unlock(action)&#xa;loadingFinished()&#xa;counter--" vertex="1">
<mxGeometry height="60" width="160" x="60" y="220" as="geometry" />
</mxCell>
</root>
Expand Down
Binary file modified docs/images/action-flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 10 additions & 10 deletions docs/images/architecture-overview.drawio
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
<mxCell id="1" parent="0"/>

<!-- Title -->
<mxCell id="2" value="Architecture Overview — The Three Pillars" style="text;html=1;fontSize=18;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="2" value="Architecture Overview — The Three Pillars" style="text;html=1;fontSize=24;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxGeometry x="100" y="20" width="600" height="40" as="geometry"/>
</mxCell>

<!-- SwiftUI View Box -->
<mxCell id="3" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;strokeWidth=2;arcSize=12;" vertex="1" parent="1">
<mxGeometry x="150" y="80" width="500" height="120" as="geometry"/>
</mxCell>
<mxCell id="4" value="SwiftUI View" style="text;html=1;fontSize=16;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="4" value="SwiftUI View" style="text;html=1;fontSize=20;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxGeometry x="310" y="82" width="180" height="30" as="geometry"/>
</mxCell>
<mxCell id="5" value="• Owns @State for ViewState and ViewModel&#xa;• Binds state to ViewModel in .task modifier&#xa;• Dispatches actions via viewModel.receive(action:)" style="text;html=1;fontSize=11;align=left;verticalAlign=top;fillColor=none;strokeColor=none;fontColor=#555555;spacingLeft=8;" vertex="1" parent="1">
<mxCell id="5" value="• Owns @State for ViewState and ViewModel&#xa;• Binds state to ViewModel in .task modifier&#xa;• Dispatches actions via viewModel.receive(action:)" style="text;html=1;fontSize=14;align=left;verticalAlign=top;fillColor=none;strokeColor=none;fontColor=#555555;spacingLeft=8;" vertex="1" parent="1">
<mxGeometry x="180" y="112" width="440" height="70" as="geometry"/>
</mxCell>
<!-- View icon -->
Expand All @@ -27,18 +27,18 @@
<mxCell id="7" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#6c8ebf;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="3" target="10">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="8" value="binds &amp; dispatches" style="text;html=1;fontSize=11;fontStyle=2;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#6c8ebf;" vertex="1" parent="1">
<mxCell id="8" value="binds &amp; dispatches" style="text;html=1;fontSize=14;fontStyle=2;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#6c8ebf;" vertex="1" parent="1">
<mxGeometry x="420" y="210" width="120" height="20" as="geometry"/>
</mxCell>

<!-- ViewModel / Store Box -->
<mxCell id="10" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;strokeWidth=2;arcSize=12;" vertex="1" parent="1">
<mxGeometry x="150" y="240" width="500" height="120" as="geometry"/>
</mxCell>
<mxCell id="11" value="ViewModel / Store (Actor)" style="text;html=1;fontSize=16;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="11" value="ViewModel / Store (Actor)" style="text;html=1;fontSize=20;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxGeometry x="280" y="242" width="240" height="30" as="geometry"/>
</mxCell>
<mxCell id="12" value="• Conforms to ScreenActionStore protocol&#xa;• Processes actions with ActionLocker&#xa;• Updates state on @MainActor" style="text;html=1;fontSize=11;align=left;verticalAlign=top;fillColor=none;strokeColor=none;fontColor=#555555;spacingLeft=8;" vertex="1" parent="1">
<mxCell id="12" value="• Conforms to ScreenActionStore protocol&#xa;• Processes actions with ActionLocker&#xa;• Updates state on @MainActor" style="text;html=1;fontSize=14;align=left;verticalAlign=top;fillColor=none;strokeColor=none;fontColor=#555555;spacingLeft=8;" vertex="1" parent="1">
<mxGeometry x="180" y="272" width="440" height="70" as="geometry"/>
</mxCell>
<!-- ViewModel icon -->
Expand All @@ -50,18 +50,18 @@
<mxCell id="14" value="" style="endArrow=classic;html=1;strokeWidth=2;strokeColor=#82b366;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="10" target="17">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="15" value="updates" style="text;html=1;fontSize=11;fontStyle=2;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#82b366;" vertex="1" parent="1">
<mxCell id="15" value="updates" style="text;html=1;fontSize=14;fontStyle=2;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="420" y="370" width="80" height="20" as="geometry"/>
</mxCell>

<!-- ViewState Box -->
<mxCell id="17" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;strokeWidth=2;arcSize=12;" vertex="1" parent="1">
<mxGeometry x="150" y="400" width="500" height="120" as="geometry"/>
</mxCell>
<mxCell id="18" value="ViewState (Observable)" style="text;html=1;fontSize=16;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxCell id="18" value="ViewState (Observable)" style="text;html=1;fontSize=20;fontStyle=1;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#333333;" vertex="1" parent="1">
<mxGeometry x="290" y="402" width="220" height="30" as="geometry"/>
</mxCell>
<mxCell id="19" value="• Extends ScreenState (@Observable @MainActor)&#xa;• Contains all UI state properties&#xa;• Inherits loading counter &amp; error handling" style="text;html=1;fontSize=11;align=left;verticalAlign=top;fillColor=none;strokeColor=none;fontColor=#555555;spacingLeft=8;" vertex="1" parent="1">
<mxCell id="19" value="• Extends ScreenState (@Observable @MainActor)&#xa;• Contains all UI state properties&#xa;• Inherits loading counter &amp; error handling" style="text;html=1;fontSize=14;align=left;verticalAlign=top;fillColor=none;strokeColor=none;fontColor=#555555;spacingLeft=8;" vertex="1" parent="1">
<mxGeometry x="180" y="432" width="440" height="70" as="geometry"/>
</mxCell>
<!-- ViewState icon -->
Expand All @@ -78,7 +78,7 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="22" value="@Observable&#xa;notifies" style="text;html=1;fontSize=11;fontStyle=2;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#d6b656;" vertex="1" parent="1">
<mxCell id="22" value="@Observable&#xa;notifies" style="text;html=1;fontSize=14;fontStyle=2;align=center;verticalAlign=middle;fillColor=none;strokeColor=none;fontColor=#d6b656;" vertex="1" parent="1">
<mxGeometry x="30" y="280" width="80" height="40" as="geometry"/>
</mxCell>

Expand Down
Binary file modified docs/images/architecture-overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading