mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-30 23:17:51 -04:00
frame: draw panel backgrounds when fullscreen hides the frame
port 1.6
This commit is contained in:
1 parent
8c42700a4c
commit
17d4ea6f88
7 files changed
+175
-13
No files matched your search
@@ -37,7 +37,7 @@ Item {
|
||||
|
||||
readonly property string resolvedConnectedBarSide: frameConnectedMode ? preferredConnectedBarSide : ""
|
||||
|
||||
readonly property bool frameOwnsConnectedChrome: frameConnectedMode && resolvedConnectedBarSide !== "" && !allowStacking && effectiveModalLayer === WlrLayer.Top && CompositorService.usesConnectedFrameChromeForScreen(effectiveScreen)
|
||||
readonly property bool frameOwnsConnectedChrome: frameConnectedMode && resolvedConnectedBarSide !== "" && !allowStacking && effectiveModalLayer === WlrLayer.Top && CompositorService.canShareConnectedFrameChromeForScreen(effectiveScreen)
|
||||
|
||||
function _dockOccupiesSide(side) {
|
||||
if (!SettingsData.showDock)
|
||||
|
||||
@@ -85,7 +85,7 @@ Item {
|
||||
|
||||
readonly property string resolvedConnectedBarSide: frameConnectedMode ? preferredConnectedBarSide : ""
|
||||
|
||||
readonly property bool frameOwnsConnectedChrome: frameConnectedMode && resolvedConnectedBarSide !== "" && effectiveLauncherLayer === WlrLayer.Top && CompositorService.usesConnectedFrameChromeForScreen(effectiveScreen)
|
||||
readonly property bool frameOwnsConnectedChrome: frameConnectedMode && resolvedConnectedBarSide !== "" && effectiveLauncherLayer === WlrLayer.Top && CompositorService.canShareConnectedFrameChromeForScreen(effectiveScreen)
|
||||
readonly property bool launcherArcExtenderActive: frameOwnsConnectedChrome && SettingsData.frameLauncherArcExtender && (resolvedConnectedBarSide === "top" || resolvedConnectedBarSide === "bottom")
|
||||
|
||||
function _dockOccupiesSide(side) {
|
||||
|
||||
@@ -661,6 +661,21 @@ Singleton {
|
||||
return FrameTransitionState.effectiveConnectedFrameModeActive && frameWindowVisibleForScreen(screenOrName);
|
||||
}
|
||||
|
||||
function canShareConnectedFrameChromeForScreen(screenOrName) {
|
||||
if (!usesConnectedFrameChromeForScreen(screenOrName))
|
||||
return false;
|
||||
if (!isHyprland)
|
||||
return true;
|
||||
|
||||
const screenName = _screenName(screenOrName);
|
||||
const monitor = Hyprland.monitors.values.find(m => m.name === screenName);
|
||||
const specialWorkspace = monitor?.lastIpcObject?.specialWorkspace?.name;
|
||||
const workspace = specialWorkspace ? Hyprland.workspaces.values.find(w => w.name === specialWorkspace) : monitor?.activeWorkspace;
|
||||
if (!workspace)
|
||||
return true;
|
||||
return !workspace.toplevels.values.some(t => t.lastIpcObject?.fullscreen === 2);
|
||||
}
|
||||
|
||||
// Connected mode renders the bar inside the frame surface.
|
||||
function frameHostsSurfacesForScreen(screenOrName) {
|
||||
return FrameTransitionState.effectiveConnectedFrameModeActive && frameConfiguredForScreen(screenOrName);
|
||||
|
||||
@@ -423,7 +423,7 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
readonly property bool frameOwnsConnectedChrome: effectivePopoutLayer === WlrLayer.Top && CompositorService.usesConnectedFrameChromeForScreen(root.screen)
|
||||
readonly property bool frameOwnsConnectedChrome: effectivePopoutLayer === WlrLayer.Top && CompositorService.canShareConnectedFrameChromeForScreen(root.screen)
|
||||
readonly property bool usesConnectedSurfaceChrome: Theme.isConnectedEffect
|
||||
readonly property bool usesLocalConnectedSurfaceChrome: usesConnectedSurfaceChrome && !frameOwnsConnectedChrome
|
||||
onFrameOwnsConnectedChromeChanged: _syncPopoutChromeState()
|
||||
|
||||
@@ -33,6 +33,9 @@ EXTERNAL_PLUGINS_DIR = REPO_ROOT / "dms-plugins-external"
|
||||
REGISTRY_DIR = EXTERNAL_PLUGINS_DIR / ".registry"
|
||||
PLUGIN_CHECKOUT_DIRS = [OFFICIAL_PLUGINS_DIR, EXTERNAL_PLUGINS_DIR]
|
||||
|
||||
PLUGIN_PR_BRANCH = "i18n/poeditor-sync"
|
||||
PLUGIN_PR_TITLE = "i18n: sync translations from POEditor"
|
||||
|
||||
# Flip once official plugins ship their own translations/ dirs: app poexports
|
||||
# then stop carrying terms owned exclusively by plugins.
|
||||
EXCLUDE_PLUGIN_ONLY_TERMS = False
|
||||
@@ -200,6 +203,103 @@ def plugin_checkouts():
|
||||
checkouts['plugin-' + child.name.lower()] = child
|
||||
return checkouts
|
||||
|
||||
def gh(args, cwd=None, required=True):
|
||||
result = subprocess.run(['gh', *args], cwd=cwd, capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
return result.stdout.strip()
|
||||
if required:
|
||||
error(f"gh {' '.join(args)} failed:\n{result.stderr.strip()}")
|
||||
return None
|
||||
|
||||
def git_output(args, cwd):
|
||||
result = subprocess.run(['git', *args], cwd=cwd, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
return None
|
||||
return result.stdout.strip()
|
||||
|
||||
def repo_slug(checkout):
|
||||
url = git_output(['remote', 'get-url', 'origin'], checkout) or ""
|
||||
if 'github.com' not in url:
|
||||
return None
|
||||
return url.removesuffix('.git').split('github.com', 1)[1].lstrip(':/')
|
||||
|
||||
def default_branch(checkout):
|
||||
ref = git_output(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], checkout)
|
||||
if not ref:
|
||||
return 'main'
|
||||
return ref.split('/', 1)[-1]
|
||||
|
||||
def pending_translation_files(checkout):
|
||||
out = git_output(['status', '--porcelain', '--untracked-files=all', '--', 'translations'], checkout)
|
||||
if not out:
|
||||
return []
|
||||
names = (line[3:].rsplit('/', 1)[-1] for line in out.splitlines())
|
||||
return sorted(name for name in names if name.endswith('.json'))
|
||||
|
||||
def pending_plugin_prs():
|
||||
external = []
|
||||
official = []
|
||||
for checkout in sorted(plugin_checkouts().values(), key=lambda path: path.name):
|
||||
files = pending_translation_files(checkout)
|
||||
if not files:
|
||||
continue
|
||||
if checkout.parent == EXTERNAL_PLUGINS_DIR:
|
||||
external.append((checkout, files))
|
||||
else:
|
||||
official.append((checkout, files))
|
||||
return external, official
|
||||
|
||||
def plugin_pr_body(files):
|
||||
return (
|
||||
"Translations synced from the DMS POEditor project, where this plugin's strings "
|
||||
"are tagged and translated alongside the shell.\n\n"
|
||||
f"Updated: {', '.join(sorted(files))}\n\n"
|
||||
"Strings this repo already shipped were uploaded to POEditor before the export, "
|
||||
"so existing translations are preserved rather than overwritten.\n"
|
||||
)
|
||||
|
||||
def open_plugin_pr(checkout, files):
|
||||
slug = repo_slug(checkout)
|
||||
if not slug:
|
||||
warn(f"{checkout.name}: origin is not a github remote, skipping PR")
|
||||
return
|
||||
|
||||
login = gh(['api', 'user', '-q', '.login'])
|
||||
fork = f"{login}/{slug.split('/', 1)[1]}"
|
||||
if gh(['repo', 'view', fork, '--json', 'name'], required=False) is None:
|
||||
info(f"Forking {slug} -> {fork}")
|
||||
gh(['repo', 'fork', slug, '--clone=false', '--remote=false'])
|
||||
|
||||
base = default_branch(checkout)
|
||||
git(['checkout', '--quiet', '-B', PLUGIN_PR_BRANCH], checkout)
|
||||
git(['add', 'translations'], checkout)
|
||||
|
||||
committed = subprocess.run(
|
||||
['git', 'commit', '--quiet', '-m', PLUGIN_PR_TITLE],
|
||||
cwd=checkout, capture_output=True, text=True
|
||||
)
|
||||
if committed.returncode != 0:
|
||||
git(['checkout', '--quiet', base], checkout)
|
||||
warn(f"{checkout.name}: nothing to commit, skipping PR")
|
||||
return
|
||||
|
||||
git(['push', '--quiet', '--force', f'[email protected]:{fork}.git', PLUGIN_PR_BRANCH], checkout)
|
||||
git(['checkout', '--quiet', base], checkout)
|
||||
|
||||
existing = gh([
|
||||
'pr', 'list', '--repo', slug, '--head', f'{login}:{PLUGIN_PR_BRANCH}',
|
||||
'--state', 'open', '--json', 'url', '-q', '.[0].url'
|
||||
], required=False)
|
||||
if existing:
|
||||
success(f"{checkout.name}: updated {existing}")
|
||||
return
|
||||
|
||||
url = gh([
|
||||
'pr', 'create', '--repo', slug, '--base', base, '--head', f'{login}:{PLUGIN_PR_BRANCH}',
|
||||
'--title', PLUGIN_PR_TITLE, '--body', plugin_pr_body(files)
|
||||
])
|
||||
success(f"{checkout.name}: opened {url}")
|
||||
|
||||
def checkout_translations(checkout, filename):
|
||||
result = subprocess.run(
|
||||
['git', 'show', f'HEAD:translations/{filename}'],
|
||||
@@ -361,7 +461,7 @@ def seed_plugin_translations(api_token, project_id, plugin_seed):
|
||||
seeded = {}
|
||||
for po_lang, values in sorted(plugin_seed.items()):
|
||||
entries = [
|
||||
{'term': term, 'context': context, 'translation': {'content': value}}
|
||||
{'term': term, 'context': context, 'definition': value}
|
||||
for (context, term), value in sorted(values.items())
|
||||
]
|
||||
info(f"Seeding {len(entries)} plugin-authored translations into POEditor ({po_lang})...")
|
||||
@@ -537,7 +637,7 @@ def save_sync_state():
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
error("Usage: i18nsync.py [check|sync [--prune]|test|local]")
|
||||
error("Usage: i18nsync.py [check|sync [--prune] [--pr] [--seed]|pr|test|local]")
|
||||
|
||||
command = sys.argv[1]
|
||||
|
||||
@@ -575,6 +675,8 @@ def main():
|
||||
api_token = get_env_or_error('POEDITOR_API_TOKEN')
|
||||
project_id = get_env_or_error('POEDITOR_PROJECT_ID')
|
||||
prune = "--prune" in sys.argv[2:]
|
||||
open_prs = "--pr" in sys.argv[2:]
|
||||
seed = "--seed" in sys.argv[2:]
|
||||
if prune:
|
||||
warn("--prune deletes every POEditor term missing from the local en.json, including its translations.")
|
||||
warn("Plugin checkouts are refreshed from the registry first, so pruning keeps terms of official and i18n-approved plugins; a plugin removed from the registry loses its terms.")
|
||||
@@ -621,7 +723,6 @@ def main():
|
||||
|
||||
plugin_owners, plugin_excluded = plugin_term_owners(current_en)
|
||||
translations_changed, common_files_changed, plugin_files_changed, plugin_seed = download_translations(api_token, project_id, common_keys, greeter_keys, plugin_owners, plugin_excluded)
|
||||
seeded = seed_plugin_translations(api_token, project_id, plugin_seed)
|
||||
|
||||
if strings_changed or translations_changed:
|
||||
subprocess.run(['git', 'add', 'translations/'], cwd=REPO_ROOT)
|
||||
@@ -635,13 +736,44 @@ def main():
|
||||
info(f"dank-qml-common poexports updated: {', '.join(common_files_changed)}")
|
||||
info("Commit those in dank-qml-common and bump the pointer here (make update-common).")
|
||||
|
||||
if seeded:
|
||||
info("Plugin-authored translations adopted into POEditor: " + ", ".join(f"{lang} +{count}" for lang, count in sorted(seeded.items())))
|
||||
|
||||
for checkout_name, files in sorted(plugin_files_changed.items()):
|
||||
info(f"{checkout_name} translations updated: {', '.join(files)}")
|
||||
if plugin_files_changed:
|
||||
info("Commit those in each plugin checkout - they ship with the plugin repo, not with DMS.")
|
||||
|
||||
pending_prs, official_pending = pending_plugin_prs()
|
||||
|
||||
for checkout, files in official_pending:
|
||||
info(f"{checkout.name}: {len(files)} translation files to commit in dms-plugins")
|
||||
|
||||
if open_prs:
|
||||
for checkout, files in pending_prs:
|
||||
open_plugin_pr(checkout, files)
|
||||
elif pending_prs:
|
||||
for checkout, files in pending_prs:
|
||||
info(f"{checkout.name} has {len(files)} uncommitted translation files")
|
||||
info("Re-run with --pr to push them to your fork and open the PRs upstream.")
|
||||
|
||||
pending_seed = sum(len(values) for values in plugin_seed.values())
|
||||
if pending_seed and not seed:
|
||||
info(f"{pending_seed} plugin-authored translations are missing from POEditor across {len(plugin_seed)} languages.")
|
||||
info("Re-run with --seed to adopt them (one throttled upload per language).")
|
||||
|
||||
if pending_seed and seed:
|
||||
seeded = seed_plugin_translations(api_token, project_id, plugin_seed)
|
||||
if seeded:
|
||||
info("Plugin-authored translations adopted into POEditor: " + ", ".join(f"{lang} +{count}" for lang, count in sorted(seeded.items())))
|
||||
|
||||
elif command == "pr":
|
||||
pending_prs, official_pending = pending_plugin_prs()
|
||||
|
||||
for checkout, files in official_pending:
|
||||
info(f"{checkout.name}: {len(files)} translation files to commit in dms-plugins")
|
||||
|
||||
if not pending_prs:
|
||||
info("No plugin checkout has uncommitted translations")
|
||||
sys.exit(0)
|
||||
|
||||
for checkout, files in pending_prs:
|
||||
open_plugin_pr(checkout, files)
|
||||
|
||||
elif command == "local":
|
||||
info("Updating en.json locally (no POEditor sync)")
|
||||
|
||||
@@ -18,6 +18,8 @@ from pathlib import Path
|
||||
|
||||
ROOT_DIR = Path(__file__).parent.parent
|
||||
|
||||
EXTERNAL_PLUGIN_PREFIX = "dms-plugins-external/"
|
||||
|
||||
# Intentional pairs that survive normalization on purpose.
|
||||
ALLOWED = [
|
||||
{"PIN", "Pin"}, # WPS PIN acronym vs the verb "pin"
|
||||
@@ -33,8 +35,19 @@ def normalize(term):
|
||||
return t + "..." if ellipsis else t
|
||||
|
||||
|
||||
def owned_occurrences(data):
|
||||
return [occ for occ in data["occurrences"]
|
||||
if not occ["file"].startswith(EXTERNAL_PLUGIN_PREFIX)]
|
||||
|
||||
|
||||
def main():
|
||||
translations = extract_qstr_strings(ROOT_DIR)
|
||||
extracted = extract_qstr_strings(ROOT_DIR)
|
||||
translations = {}
|
||||
for term, data in extracted.items():
|
||||
occurrences = owned_occurrences(data)
|
||||
if occurrences:
|
||||
translations[term] = occurrences
|
||||
|
||||
groups = defaultdict(set)
|
||||
for term in translations:
|
||||
groups[normalize(term)].add(term)
|
||||
@@ -59,7 +72,7 @@ def main():
|
||||
for variants in sorted(failures):
|
||||
print(f" {variants}", file=sys.stderr)
|
||||
for v in variants:
|
||||
for occ in translations[v]["occurrences"][:3]:
|
||||
for occ in translations[v][:3]:
|
||||
print(f" {v!r}: {occ['file']}:{occ['line']}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -203,12 +203,14 @@ def main():
|
||||
en_json_path = translations_dir / 'en.json'
|
||||
with open(en_json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(poeditor_data, f, indent=2, ensure_ascii=False)
|
||||
f.write('\n')
|
||||
print(f"Created source language file: {en_json_path}")
|
||||
|
||||
template_data = create_template_json(translations)
|
||||
template_json_path = translations_dir / 'template.json'
|
||||
with open(template_json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(template_data, f, indent=2, ensure_ascii=False)
|
||||
f.write('\n')
|
||||
print(f"Created template file: {template_json_path}")
|
||||
|
||||
print("\nSummary:")
|
||||
|
||||
Reference in new issue
Block a user