v1.0.24: harmonious icon, recursive file watching, download-then-open, security fixes

Icon: three identical parallel arcing arrows (same bezier curve, same blue-to-teal
gradient #64C8FF→#32EDBB, same arrowhead geometry) — visually cohesive and clearly
visible against the near-black background.

FileWatchService: FileObserver is now recursive — watchDirRecursive() creates an
observer for each subdirectory at startup, and adds new watchers when CREATE events
produce new directories. Fixes files added to subdirectories not being detected.

FilesViewModel: openFile/shareFile now fall back to download-then-open when the file
is absent locally. AccountRepository + ProviderFactory injected; downloads to
context.cacheDir/syncflow_open/ with isDownloading state. Path traversal guard added
(reject relativePath containing ".."). file_paths.xml gains cache-path entry.

WebDavProvider: path-traversal guard in parsePropfind — skip any server-returned
filename containing "..", "/" or "\". Replace android.util.Log with Timber so debug
logs are stripped from release builds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 00:37:16 +00:00
parent 08dc4f5bd4
commit 146b8baf9a
8 changed files with 184 additions and 86 deletions
@@ -6,90 +6,61 @@
android:viewportWidth="108"
android:viewportHeight="108">
<!-- Subtle inner glow -->
<path
android:pathData="M54,54m-30,0a30,30 0 1,0 60,0a30,30 0 1,0 -60,0"
android:fillColor="#0AFFFFFF"/>
<!--
Three identical arcs pointing right, evenly spaced vertically.
Same curve shape, same gradient direction, same arrowhead geometry — purely harmonious.
Control point 14dp above midline on each arc.
-->
<!-- ═══ Arrow 1: curving RIGHT (top) — coral gradient ═══ -->
<!-- Curved shaft via quadratic bezier: left→ dips up → right -->
<!-- Arc 1 — top -->
<path
android:pathData="M28,40 Q54,22 80,36"
android:pathData="M 26,34 Q 54,20 82,34"
android:fillColor="#00000000"
android:strokeWidth="7"
android:strokeWidth="8.5"
android:strokeLineCap="round"
android:strokeLineJoin="round">
<aapt:attr name="android:strokeColor">
<gradient android:type="linear"
android:startX="28" android:startY="36"
android:endX="80" android:endY="36"
android:startColor="#FF6B6B"
android:endColor="#FFB347"/>
</aapt:attr>
</path>
<!-- Arrowhead at (80,36) pointing right/slightly-down -->
<path android:pathData="M76,28 L72,44 L88,38 Z">
<aapt:attr name="android:fillColor">
<gradient android:type="linear"
android:startX="72" android:startY="36"
android:endX="88" android:endY="36"
android:startColor="#FFB347"
android:endColor="#FF8C42"/>
android:startX="26" android:startY="34"
android:endX="82" android:endY="34"
android:startColor="#64C8FF"
android:endColor="#32EDBB"/>
</aapt:attr>
</path>
<path android:pathData="M 77.5,27.3 L 82,34 L 74.0,34.5 Z" android:fillColor="#32EDBB"/>
<!-- ═══ Arrow 2: curving LEFT (middle) — silver/white ═══ -->
<!-- Curved shaft: right→ dips down → left -->
<!-- Arc 2 — middle -->
<path
android:pathData="M80,56 Q54,74 28,60"
android:pathData="M 26,54 Q 54,40 82,54"
android:fillColor="#00000000"
android:strokeWidth="7"
android:strokeWidth="8.5"
android:strokeLineCap="round"
android:strokeLineJoin="round">
<aapt:attr name="android:strokeColor">
<gradient android:type="linear"
android:startX="80" android:startY="60"
android:endX="28" android:endY="60"
android:startColor="#D0D8EE"
android:endColor="#8892AA"/>
</aapt:attr>
</path>
<!-- Arrowhead at (28,60) pointing left/slightly-down -->
<path android:pathData="M32,52 L36,68 L20,62 Z">
<aapt:attr name="android:fillColor">
<gradient android:type="linear"
android:startX="36" android:startY="60"
android:endX="20" android:endY="60"
android:startColor="#D0D8EE"
android:endColor="#8892AA"/>
android:startX="26" android:startY="54"
android:endX="82" android:endY="54"
android:startColor="#64C8FF"
android:endColor="#32EDBB"/>
</aapt:attr>
</path>
<path android:pathData="M 77.5,47.3 L 82,54 L 74.0,54.5 Z" android:fillColor="#32EDBB"/>
<!-- ═══ Arrow 3: curving RIGHT (bottom) — teal gradient ═══ -->
<!-- Curved shaft: left→ dips up → right -->
<!-- Arc 3 — bottom -->
<path
android:pathData="M28,74 Q54,58 80,72"
android:pathData="M 26,74 Q 54,60 82,74"
android:fillColor="#00000000"
android:strokeWidth="7"
android:strokeWidth="8.5"
android:strokeLineCap="round"
android:strokeLineJoin="round">
<aapt:attr name="android:strokeColor">
<gradient android:type="linear"
android:startX="28" android:startY="72"
android:endX="80" android:endY="72"
android:startColor="#4DD0E1"
android:endColor="#00BCD4"/>
</aapt:attr>
</path>
<!-- Arrowhead at (80,72) pointing right/slightly-up -->
<path android:pathData="M76,64 L72,80 L88,74 Z">
<aapt:attr name="android:fillColor">
<gradient android:type="linear"
android:startX="72" android:startY="72"
android:endX="88" android:endY="72"
android:startColor="#00BCD4"
android:endColor="#00ACC1"/>
android:startX="26" android:startY="74"
android:endX="82" android:endY="74"
android:startColor="#64C8FF"
android:endColor="#32EDBB"/>
</aapt:attr>
</path>
<path android:pathData="M 77.5,67.3 L 82,74 L 74.0,74.5 Z" android:fillColor="#32EDBB"/>
</vector>