draftwatch 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {draftwatch-0.2.2 → draftwatch-0.2.3}/PKG-INFO +1 -1
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/app.py +64 -20
- draftwatch-0.2.3/draftwatch/assets/favicon.png +0 -0
- draftwatch-0.2.3/draftwatch/assets/icon.png +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch.egg-info/PKG-INFO +1 -1
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch.egg-info/SOURCES.txt +2 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/pyproject.toml +1 -1
- {draftwatch-0.2.2 → draftwatch-0.2.3}/LICENSE +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/README.md +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/__init__.py +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/__main__.py +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/assets/codemirror.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/assets/marked.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/assets/purify.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/assets/turndown.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/assets/xterm.css +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/assets/xterm.js +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch/term.py +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch.egg-info/dependency_links.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch.egg-info/entry_points.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch.egg-info/requires.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/draftwatch.egg-info/top_level.txt +0 -0
- {draftwatch-0.2.2 → draftwatch-0.2.3}/setup.cfg +0 -0
|
@@ -40,7 +40,7 @@ TERM_SUPPORTED = _term is not None
|
|
|
40
40
|
# Single source of truth for the version and the date of the latest release.
|
|
41
41
|
# __init__.py re-exports __version__; the About panel shows both (injected into
|
|
42
42
|
# the served page from these constants).
|
|
43
|
-
__version__ = "0.2.
|
|
43
|
+
__version__ = "0.2.3"
|
|
44
44
|
RELEASE_DATE = "2026-09-23"
|
|
45
45
|
|
|
46
46
|
# Preferred port. When --port is not given, Draftwatch tries this first and
|
|
@@ -840,6 +840,7 @@ STATIC_ASSETS = {
|
|
|
840
840
|
"marked.js": "application/javascript; charset=utf-8",
|
|
841
841
|
"purify.js": "application/javascript; charset=utf-8",
|
|
842
842
|
"turndown.js": "application/javascript; charset=utf-8",
|
|
843
|
+
"favicon.png": "image/png",
|
|
843
844
|
}
|
|
844
845
|
|
|
845
846
|
|
|
@@ -1462,6 +1463,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1462
1463
|
<meta name="referrer" content="no-referrer">
|
|
1463
1464
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1464
1465
|
<title>Draftwatch</title>
|
|
1466
|
+
<link rel="icon" type="image/png" href="/static/favicon.png">
|
|
1465
1467
|
<script src="/static/codemirror.js"></script>
|
|
1466
1468
|
<script src="/static/marked.js"></script>
|
|
1467
1469
|
<script src="/static/purify.js"></script>
|
|
@@ -1617,7 +1619,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1617
1619
|
|
|
1618
1620
|
/* app chrome (native window via pywebview, ?app=1): the OS title bar
|
|
1619
1621
|
already says "draftwatch · file", so the in-page wordmark is redundant —
|
|
1620
|
-
drop
|
|
1622
|
+
drop the word (the logo, outside .title, stays as the brand), tighten the toolbar, and make the chrome feel native (no text
|
|
1621
1623
|
selection on controls, no web-page tells). */
|
|
1622
1624
|
body.app-mode header .title { display: none; }
|
|
1623
1625
|
body.app-mode header { padding: 5px 10px; }
|
|
@@ -1638,14 +1640,22 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1638
1640
|
display: flex;
|
|
1639
1641
|
flex-direction: column;
|
|
1640
1642
|
}
|
|
1643
|
+
/* logo on the left, spanning both toolbar rows; the rows stack beside it */
|
|
1641
1644
|
header {
|
|
1642
1645
|
display: flex;
|
|
1643
|
-
|
|
1644
|
-
gap:
|
|
1646
|
+
align-items: center;
|
|
1647
|
+
gap: 10px;
|
|
1645
1648
|
padding: 8px 12px;
|
|
1646
1649
|
border-bottom: 1px solid var(--border);
|
|
1647
1650
|
background: var(--panel);
|
|
1648
1651
|
}
|
|
1652
|
+
header .rows {
|
|
1653
|
+
flex: 1;
|
|
1654
|
+
min-width: 0;
|
|
1655
|
+
display: flex;
|
|
1656
|
+
flex-direction: column;
|
|
1657
|
+
gap: 6px;
|
|
1658
|
+
}
|
|
1649
1659
|
/* Two fixed rows that never wrap into each other, so the layout stays put
|
|
1650
1660
|
regardless of title length or window width:
|
|
1651
1661
|
row 1 = what you're looking at (title, file picker, baseline selector —
|
|
@@ -1668,19 +1678,11 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
1668
1678
|
gap: 7px;
|
|
1669
1679
|
letter-spacing: .02em;
|
|
1670
1680
|
}
|
|
1671
|
-
/* the
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
border: 1px solid var(--border);
|
|
1677
|
-
border-radius: 5px;
|
|
1678
|
-
padding: 0 5px;
|
|
1679
|
-
font-weight: 700;
|
|
1680
|
-
line-height: 1.45;
|
|
1681
|
-
}
|
|
1682
|
-
.mark .ma { color: var(--add-fg); }
|
|
1683
|
-
.mark .md { color: var(--del-fg); text-decoration: line-through; }
|
|
1681
|
+
/* the logo: same drawing as the Dock icon and favicon (scripts/make_icon.py),
|
|
1682
|
+
inline so it stays crisp at any size. Fixed brand colors, not the accent. */
|
|
1683
|
+
.logo { width: 28px; height: 28px; flex: none; display: block; }
|
|
1684
|
+
header > .logo { width: 54px; height: 54px; }
|
|
1685
|
+
#about h2 .logo { width: 48px; height: 48px; }
|
|
1684
1686
|
header .status { color: var(--muted); }
|
|
1685
1687
|
header #status {
|
|
1686
1688
|
flex: 1 1 auto;
|
|
@@ -2067,9 +2069,26 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
2067
2069
|
</style>
|
|
2068
2070
|
</head>
|
|
2069
2071
|
<body>
|
|
2072
|
+
<!-- logo geometry mirrors scripts/make_icon.py (1024 grid, tile at 100..924) -->
|
|
2073
|
+
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
|
|
2074
|
+
<defs>
|
|
2075
|
+
<linearGradient id="dw-logo-bg" x1="0" y1="0" x2="0" y2="1">
|
|
2076
|
+
<stop offset="0" stop-color="#3d82c7"/><stop offset="1" stop-color="#215892"/>
|
|
2077
|
+
</linearGradient>
|
|
2078
|
+
<symbol id="dw-logo" viewBox="100 100 824 824">
|
|
2079
|
+
<rect x="100" y="100" width="824" height="824" rx="185" fill="url(#dw-logo-bg)"/>
|
|
2080
|
+
<path fill="#f5f9fe" fill-rule="evenodd"
|
|
2081
|
+
d="M322 262H488A250 250 0 0 1 488 762H322Z M428 368H488A144 144 0 0 1 488 656H428Z"/>
|
|
2082
|
+
<rect x="470" y="452" width="120" height="42" rx="21" fill="#7ed08a"/>
|
|
2083
|
+
<rect x="470" y="530" width="92" height="42" rx="21" fill="#f08e7f"/>
|
|
2084
|
+
</symbol>
|
|
2085
|
+
</defs>
|
|
2086
|
+
</svg>
|
|
2070
2087
|
<header>
|
|
2088
|
+
<svg class="logo" aria-hidden="true"><use href="#dw-logo"/></svg>
|
|
2089
|
+
<div class="rows">
|
|
2071
2090
|
<div class="bar">
|
|
2072
|
-
<span class="title"><span class="
|
|
2091
|
+
<span class="title"><span class="word">Draftwatch</span></span>
|
|
2073
2092
|
<span class="filepick">
|
|
2074
2093
|
<label class="status" for="file-select">file</label>
|
|
2075
2094
|
<select id="file-select" title="pick a writing file in this repo"></select>
|
|
@@ -2094,6 +2113,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
2094
2113
|
<button id="accent-toggle" title="accent color — click to cycle"><span class="swatch"></span><span id="accent-name">blue</span></button>
|
|
2095
2114
|
<button id="about-btn" title="what is Draftwatch?">about</button>
|
|
2096
2115
|
</div>
|
|
2116
|
+
</div>
|
|
2097
2117
|
</header>
|
|
2098
2118
|
|
|
2099
2119
|
<div id="banner">
|
|
@@ -2106,7 +2126,7 @@ INDEX_HTML = r"""<!DOCTYPE html>
|
|
|
2106
2126
|
<div id="about" role="dialog" aria-modal="true" aria-label="About Draftwatch">
|
|
2107
2127
|
<div class="card">
|
|
2108
2128
|
<button class="about-close" id="about-close" title="close (Esc)">close ✕</button>
|
|
2109
|
-
<h2><
|
|
2129
|
+
<h2><svg class="logo" aria-hidden="true"><use href="#dw-logo"/></svg>Draftwatch</h2>
|
|
2110
2130
|
<p class="tag">Review an AI agent's edits as a real git diff — locally.</p>
|
|
2111
2131
|
<p>An autonomous agent (Claude Code and the like) edits your files on disk.
|
|
2112
2132
|
Draftwatch shows you exactly what changed, as the word-level diff
|
|
@@ -3799,6 +3819,30 @@ def _webview_available():
|
|
|
3799
3819
|
return False
|
|
3800
3820
|
|
|
3801
3821
|
|
|
3822
|
+
def _app_identity_kwargs(webview):
|
|
3823
|
+
"""Brand the native window as Draftwatch rather than the Python interpreter
|
|
3824
|
+
running it: the Dock icon (draftwatch/assets/icon.png, drawn by
|
|
3825
|
+
scripts/make_icon.py) and, on macOS, the app name in the menu bar and its
|
|
3826
|
+
About/Hide/Quit items. Best effort: any failure leaves pywebview's defaults.
|
|
3827
|
+
Returns the kwargs for webview.start()."""
|
|
3828
|
+
if sys.platform == "darwin":
|
|
3829
|
+
try:
|
|
3830
|
+
from Foundation import NSBundle # PyObjC, a pywebview dependency on macOS
|
|
3831
|
+
info = NSBundle.mainBundle().infoDictionary()
|
|
3832
|
+
if info is not None:
|
|
3833
|
+
info["CFBundleName"] = "Draftwatch"
|
|
3834
|
+
except Exception:
|
|
3835
|
+
pass
|
|
3836
|
+
icon = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "icon.png")
|
|
3837
|
+
try:
|
|
3838
|
+
import inspect
|
|
3839
|
+
takes_icon = "icon" in inspect.signature(webview.start).parameters
|
|
3840
|
+
except (TypeError, ValueError):
|
|
3841
|
+
takes_icon = False
|
|
3842
|
+
# start(icon=) arrived in pywebview 5; on 4.x the window just keeps its default
|
|
3843
|
+
return {"icon": icon} if takes_icon and os.path.isfile(icon) else {}
|
|
3844
|
+
|
|
3845
|
+
|
|
3802
3846
|
def _run_app_window(url, title):
|
|
3803
3847
|
"""Open the UI in a native window (PyWebView). Returns True when the window
|
|
3804
3848
|
ran and was closed by the user; False when unavailable, in which case the
|
|
@@ -3816,7 +3860,7 @@ def _run_app_window(url, title):
|
|
|
3816
3860
|
try:
|
|
3817
3861
|
webview.create_window(title, url, width=1280, height=860,
|
|
3818
3862
|
min_size=(880, 560))
|
|
3819
|
-
webview.start()
|
|
3863
|
+
webview.start(**_app_identity_kwargs(webview))
|
|
3820
3864
|
return True
|
|
3821
3865
|
except Exception as e:
|
|
3822
3866
|
sys.stderr.write(
|
|
Binary file
|
|
Binary file
|
|
@@ -12,6 +12,8 @@ draftwatch.egg-info/entry_points.txt
|
|
|
12
12
|
draftwatch.egg-info/requires.txt
|
|
13
13
|
draftwatch.egg-info/top_level.txt
|
|
14
14
|
draftwatch/assets/codemirror.js
|
|
15
|
+
draftwatch/assets/favicon.png
|
|
16
|
+
draftwatch/assets/icon.png
|
|
15
17
|
draftwatch/assets/marked.js
|
|
16
18
|
draftwatch/assets/purify.js
|
|
17
19
|
draftwatch/assets/turndown.js
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "draftwatch"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Review an AI agent's edits to your writing files as a real git word-diff — keep or revert changes hunk by hunk, then commit."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|