Suppress the Cloudpinyin first-use prompt

This commit is contained in:
David Heinemeier Hansson committed 2026-10-07 17:48:56 +02:00
1 parent 036e501e58
commit f273eed840
5 files changed
+29 -7

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# Keep Pinyin offline without prompting to enable cloud prediction.
FirstRun=False
CloudPinyinEnabled=False
+12 -2
View File
@@ -74,7 +74,7 @@ def key_list(entries):
def defaults(config_home, fresh=False):
changed = False
files = ["config", "conf/quickphrase.conf", "conf/wayland.conf", "conf/xcb.conf"]
files = ["config", "conf/quickphrase.conf", "conf/wayland.conf", "conf/xcb.conf", "conf/pinyin.conf"]
for name in files:
target = config_home / "fcitx5" / name
original = read(target)
@@ -104,6 +104,16 @@ def defaults(config_home, fresh=False):
additions.append(f"[{section}]\n" + "".join(f"{key}={value}\n" for key, value in entries.items()))
if additions:
changed |= atomic_write(target, original.rstrip() + ("\n\n" if original.strip() else "") + "\n".join(additions))
elif name == "conf/pinyin.conf":
# Suppress the first-use cloud prompt while preserving any explicit
# cloud-prediction preference and all other existing engine settings.
if not original:
updated = shipped
elif "FirstRun" in values(original):
updated = re.sub(r"(?m)^\s*FirstRun\s*=.*$", "FirstRun=False", original)
else:
updated = "FirstRun=False\n" + original
changed |= atomic_write(target, updated)
elif not target.exists() and not target.is_symlink():
changed |= atomic_write(target, shipped)
return changed
@@ -123,7 +133,7 @@ def activation_default():
@contextmanager
def transaction(config_home, live=False):
data_home = Path(os.environ.get("XDG_DATA_HOME") or str(Path.home() / ".local/share"))
paths = [config_home / "fcitx5" / name for name in ["profile", "config", "conf/quickphrase.conf", "conf/wayland.conf", "conf/xcb.conf"]]
paths = [config_home / "fcitx5" / name for name in ["profile", "config", "conf/quickphrase.conf", "conf/wayland.conf", "conf/xcb.conf", "conf/pinyin.conf"]]
paths += [config_home / "fontconfig/conf.d/50-omarchy-input-method.conf", data_home / "dbus-1/services/org.fcitx.Fcitx5.service"]
before = {path.resolve(): path.read_text() if path.exists() else None for path in paths}
try:
@@ -202,9 +202,7 @@ function snapshotOf(notification, timestamp) {
glyph: glyphFromHints(n.hints),
execArgv: execArgvFromHints(n.hints),
actionsJson: JSON.stringify(actions),
// Pinyin's first-use cloud prediction question needs an explicit answer.
// Its normal urgency otherwise dismisses it before users can read it.
urgency: n.appName === "Pinyin" && n.appIcon === "fcitx-pinyin" ? 2 : n.urgency,
urgency: n.urgency,
expireTimeout: expireTimeout,
timestamp: timestamp === undefined ? Date.now() : timestamp
}
+13
View File
@@ -16,6 +16,19 @@ spec.loader.exec_module(setup)
class InputMethodTest(unittest.TestCase):
def test_pinyin_defaults_suppress_cloud_prompt(self):
setup.defaults(self.config, fresh=True)
pinyin = setup.values((self.config / "fcitx5/conf/pinyin.conf").read_text())
self.assertEqual(pinyin["FirstRun"], "False")
self.assertEqual(pinyin["CloudPinyinEnabled"], "False")
def test_pinyin_prompt_suppression_preserves_existing_preferences(self):
pinyin = self.config / "fcitx5/conf/pinyin.conf"
pinyin.parent.mkdir(parents=True)
pinyin.write_text("FirstRun=True\nCloudPinyinEnabled=True\nPageSize=7\n")
setup.defaults(self.config)
self.assertEqual(pinyin.read_text(), "FirstRun=False\nCloudPinyinEnabled=True\nPageSize=7\n")
def setUp(self):
self.temporary = tempfile.TemporaryDirectory()
self.addCleanup(self.temporary.cleanup)
-2
View File
@@ -275,8 +275,6 @@ assertDeepEqual(JSON.parse(notifications.snapshotOf({ actions: [
{ identifier: 'default', text: 'Open' }, { identifier: 'yes', text: 'Yes' }, { identifier: 'no', text: 'No' }
]}).actionsJson), [{ identifier: 'yes', text: 'Yes' }, { identifier: 'no', text: 'No' }], 'explicit choices appear independently of the default card action')
assertEqual(notifications.popupEntry({ actionsJson: '[{"identifier":"yes","text":"Yes"}]' }, 1).actionsJson, '[]', 'restored notifications do not replay actions from a dead sender')
assertEqual(notifications.snapshotOf({ appName: 'Pinyin', appIcon: 'fcitx-pinyin', urgency: 1 }).urgency, 2, 'Pinyin prompts stay visible until dismissed')
assertEqual(notifications.snapshotOf({ appName: 'Other', appIcon: 'fcitx-pinyin', urgency: 1 }).urgency, 1, 'other notification senders retain their urgency')
assertDeepEqual(
{
id: snapshot.id,