diff --git a/gonotego/settings-server/src/App.tsx b/gonotego/settings-server/src/App.tsx index 68e782b..1d8530b 100644 --- a/gonotego/settings-server/src/App.tsx +++ b/gonotego/settings-server/src/App.tsx @@ -59,6 +59,7 @@ const SettingsUI = () => { GOOGLE_DOCS_SHARE_EMAIL: '', GOOGLE_DOCS_FOLDER_ID: '', GOOGLE_DOCS_TITLE_FORMAT: '', + GOOGLE_DOCS_FONT: '', DROPBOX_ACCESS_TOKEN: '', OPENAI_API_KEY: '', WIFI_NETWORKS: [], @@ -736,7 +737,8 @@ const SettingsUI = () => { { key: 'GOOGLE_DOCS_CREDENTIALS', label: 'Service Account JSON Path', tip: 'Path on the device to the service-account credentials file' }, { key: 'GOOGLE_DOCS_SHARE_EMAIL', label: 'Share With Email', tip: 'Each monthly doc is shared with this address as an editor' }, { key: 'GOOGLE_DOCS_FOLDER_ID', label: 'Drive Folder ID', tip: 'Optional: Drive folder to create the monthly docs in' }, - { key: 'GOOGLE_DOCS_TITLE_FORMAT', label: 'Doc Title Format', tip: "Optional strftime for the monthly doc title, default '%B %Y'" }, + { key: 'GOOGLE_DOCS_TITLE_FORMAT', label: 'Doc Title Format', tip: "Optional strftime for the monthly doc title, default 'Go Note Go Notes - %B %Y'" }, + { key: 'GOOGLE_DOCS_FONT', label: 'Font', tip: "Optional: one font family for the whole doc (e.g. Trebuchet MS). Blank keeps Google Docs' default two-font styling" }, ], shouldShowSection('googledocs'))} {renderSettingGroup('Slack', 'Slack integration settings', [ diff --git a/gonotego/settings/secure_settings_template.py b/gonotego/settings/secure_settings_template.py index 5fadd7d..16f4767 100644 --- a/gonotego/settings/secure_settings_template.py +++ b/gonotego/settings/secure_settings_template.py @@ -37,6 +37,7 @@ GOOGLE_DOCS_SHARE_EMAIL = '' GOOGLE_DOCS_FOLDER_ID = '' GOOGLE_DOCS_TITLE_FORMAT = '' +GOOGLE_DOCS_FONT = '' DROPBOX_ACCESS_TOKEN = '' diff --git a/gonotego/uploader/googledocs/googledocs_uploader.py b/gonotego/uploader/googledocs/googledocs_uploader.py index a4f6b48..6f092a8 100644 --- a/gonotego/uploader/googledocs/googledocs_uploader.py +++ b/gonotego/uploader/googledocs/googledocs_uploader.py @@ -32,7 +32,7 @@ DAY_STYLE = 'HEADING_1' SESSION_STYLE = 'HEADING_2' BULLET_PRESET = 'BULLET_DISC_CIRCLE_SQUARE' -DEFAULT_TITLE_FORMAT = '%B %Y' +DEFAULT_TITLE_FORMAT = 'Go Note Go Notes - %B %Y' def clip(x, a, b): @@ -203,6 +203,17 @@ def _build_requests(self, insert_index, blob, paragraphs): """ requests = [{'insertText': { 'location': {'index': insert_index}, 'text': blob}}] + # Optionally force a single font across the whole insert (headings + notes). + # Without GOOGLE_DOCS_FONT set, Google Docs' default two-font styling is kept + # (Trebuchet MS headings, Arial body). Applied before the bullet requests + # below, which shift indices by removing tabs; a text-style change has no + # length effect, so this range stays valid. + font = _setting('GOOGLE_DOCS_FONT') + if font: + requests.append({'updateTextStyle': { + 'range': {'startIndex': insert_index, 'endIndex': insert_index + len(blob)}, + 'textStyle': {'weightedFontFamily': {'fontFamily': font}}, + 'fields': 'weightedFontFamily'}}) styling = [] # (start_index, request) i = 0 n = len(paragraphs) diff --git a/gonotego/uploader/googledocs/test_googledocs_uploader.py b/gonotego/uploader/googledocs/test_googledocs_uploader.py index c1d7758..5301467 100644 --- a/gonotego/uploader/googledocs/test_googledocs_uploader.py +++ b/gonotego/uploader/googledocs/test_googledocs_uploader.py @@ -88,9 +88,9 @@ def test_single_session_layout(): ok = up.upload([note(events.SUBMIT, 'first', ts), note(events.SUBMIT, 'second', ts)]) assert ok is True - assert client.created == [('September 2026', None, None)] + assert client.created == [('Go Note Go Notes - September 2026', None, None)] doc_id, requests = client.batches[0] - assert doc_id == 'doc:September 2026' + assert doc_id == 'doc:Go Note Go Notes - September 2026' day = gd.day_title(datetime(2026, 9, 8, 6, 30)) session = gd.session_title(datetime(2026, 9, 8, 6, 30)) assert insert_text(requests) == f'{day}\n{session}\nfirst\nsecond\n' @@ -170,7 +170,7 @@ def test_existing_day_heading_in_doc_is_not_repeated(): up = gd.Uploader(client=client) today = gd.day_title(datetime(2026, 9, 8, 6, 30)) # Pre-create the month doc and mark today's heading already present. - doc_id = client.get_or_create_month_doc('September 2026') + doc_id = client.get_or_create_month_doc('Go Note Go Notes - September 2026') client.set_existing_day(doc_id, today) up.upload([note(events.SUBMIT, 'x')]) _, requests = client.batches[0] @@ -192,14 +192,14 @@ def test_folder_and_share_settings_passed(stub_settings): stub_settings['GOOGLE_DOCS_SHARE_EMAIL'] = 'andrea@example.com' client = FakeClient() gd.Uploader(client=client).upload([note(events.SUBMIT, 'x')]) - assert client.created == [('September 2026', 'folderX', 'andrea@example.com')] + assert client.created == [('Go Note Go Notes - September 2026', 'folderX', 'andrea@example.com')] def test_placeholder_settings_treated_as_unset(stub_settings): stub_settings['GOOGLE_DOCS_SHARE_EMAIL'] = '' client = FakeClient() gd.Uploader(client=client).upload([note(events.SUBMIT, 'x')]) - assert client.created == [('September 2026', None, None)] + assert client.created == [('Go Note Go Notes - September 2026', None, None)] def test_custom_title_format(stub_settings): @@ -209,6 +209,29 @@ def test_custom_title_format(stub_settings): assert client.created[0][0] == 'GNG 2026-09' +def test_default_keeps_two_fonts_no_override(): + client = FakeClient() + gd.Uploader(client=client).upload([note(events.SUBMIT, 'x')]) + _, requests = client.batches[0] + assert not any('updateTextStyle' in r for r in requests) + + +def test_google_docs_font_setting_applies_one_font(stub_settings): + stub_settings['GOOGLE_DOCS_FONT'] = 'Trebuchet MS' + client = FakeClient() + gd.Uploader(client=client).upload([note(events.SUBMIT, 'first'), note(events.SUBMIT, 'second')]) + _, requests = client.batches[0] + font_reqs = [r for r in requests if 'updateTextStyle' in r] + assert len(font_reqs) == 1 + style = font_reqs[0]['updateTextStyle'] + assert style['textStyle']['weightedFontFamily']['fontFamily'] == 'Trebuchet MS' + insert = requests[0]['insertText'] + assert style['range']['startIndex'] == insert['location']['index'] + assert style['range']['endIndex'] == insert['location']['index'] + len(insert['text']) + kinds = [next(iter(r)) for r in requests] + assert kinds.index('updateTextStyle') < kinds.index('createParagraphBullets') + + def test_empty_submits_skipped(): client = FakeClient() up = gd.Uploader(client=client)