Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,7 @@ android/app/src/main/jniLibs/
/third_party/fvp/android/.cxx/
/third_party/fvp/android/mdk-sdk/
/third_party/fvp/android/mdk-sdk-*.7z

# OHOS plugin overlay working copies (scripts/enable-ohos-plugins.sh)
/pubspec.yaml.ohos-backup
/pubspec.lock.ohos-backup
64 changes: 64 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.3"
app_links_ohos:
dependency: "direct main"
description:
name: app_links_ohos
sha256: "00c85e64f8e770570748a66659f008cca0be13d18d5286afd536b7555676e2ba"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
app_links_platform_interface:
dependency: transitive
description:
Expand Down Expand Up @@ -968,6 +976,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.4"
local_auth_ohos:
dependency: "direct main"
description:
name: local_auth_ohos
sha256: "9287c3f347b2530aeb7b777f2ffd1c1df256866430634735cb5418fd186d9fc7"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
local_auth_platform_interface:
dependency: transitive
description:
Expand Down Expand Up @@ -1096,6 +1112,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.7.0"
open_filex_ohos:
dependency: "direct main"
description:
name: open_filex_ohos
sha256: aefe74a34ec21e08e609c4cb7c3e4f5110512ea1c5bedf72bfddc44f9fb103e1
url: "https://pub.dev"
source: hosted
version: "4.7.0"
package_config:
dependency: transitive
description:
Expand Down Expand Up @@ -1168,6 +1192,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.2"
path_provider_ohos:
dependency: "direct main"
description:
name: path_provider_ohos
sha256: "6b479a99543743a9e0882f69521345b1ec78ceacb50ba155dffd43d01b1f84d0"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
Expand Down Expand Up @@ -1464,6 +1496,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.1.0"
sensors_plus_ohos:
dependency: "direct main"
description:
name: sensors_plus_ohos
sha256: aa179afb15d2834dfde0cbb5271f1a541a5859e0258467085a535e0c142065cb
url: "https://pub.dev"
source: hosted
version: "0.1.2"
sensors_plus_platform_interface:
dependency: transitive
description:
Expand Down Expand Up @@ -1520,6 +1560,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_ohos:
dependency: "direct main"
description:
name: shared_preferences_ohos
sha256: "4f143582552822b4198491a5ddfa066e3e2658d646a8e55302267e77379f00d0"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shared_preferences_platform_interface:
dependency: "direct dev"
description:
Expand Down Expand Up @@ -1725,6 +1773,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.6"
url_launcher_ohos:
dependency: "direct main"
description:
name: url_launcher_ohos
sha256: a6ab56765be876fbcfac6f2a8de4f5bc5dc62b0c66e0fa37e33db263cb5d4ba7
url: "https://pub.dev"
source: hosted
version: "6.3.0"
url_launcher_platform_interface:
dependency: transitive
description:
Expand Down Expand Up @@ -1877,6 +1933,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.14.1"
webview_flutter_ohos:
dependency: "direct main"
description:
name: webview_flutter_ohos
sha256: da80d6318df3ca437898f21c04249cfe63e4df2893b7fd2a4b4e9cecf964bb6b
url: "https://pub.dev"
source: hosted
version: "3.15.0"
webview_flutter_platform_interface:
dependency: transitive
description:
Expand Down
32 changes: 32 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,38 @@ dependencies:
local_auth: ^3.0.2
app_links: ^7.2.1

# HarmonyOS (OpenHarmony) federated plugin implementations. Each port below
# declares a `platforms: ohos` plugin (most also `implements:` the host
# package); stock flutter_tools ignores the ohos platform on Android/iOS/
# desktop, while the OHOS Flutter fork resolves these as the platform
# implementation when building for HarmonyOS. Regular dependencies (not
# overrides) so the OHOS solver sees them; harmless elsewhere.
# The remaining ports (package_info_plus / permission_handler / file_picker /
# geolocator / flutter_secure_storage _ohos) cap their SDK at <3.0.0 and so
# cannot resolve under stock Dart 3; they live in pubspec_overrides.ohos.yaml
# and are merged in by scripts/enable-ohos-plugins.sh for OHOS builds.
# NOTE: camera / mobile_scanner / flutter_sound / photo_manager /
# flutter_local_notifications have no ohos port on pub yet — those
# capabilities are missing on HarmonyOS for now.

# Persisted preferences on OHOS (implements shared_preferences).
shared_preferences_ohos: ^2.2.0
# TDLib database / files directories on OHOS (implements path_provider).
path_provider_ohos: ^2.2.1
# External links and the system viewer on OHOS (implements url_launcher).
url_launcher_ohos: ^6.3.0
# Accelerometer/gyroscope on OHOS — companion plugin whose native side
# serves sensors_plus' channels (sensors_plus has no ohos platform entry).
sensors_plus_ohos: ^0.1.2
# Deep links (t.me / tg://) on OHOS — companion for app_links.
app_links_ohos: ^0.2.0
# Opening downloaded files on OHOS (implements open_filex).
open_filex_ohos: ^4.7.0
# Biometric unlock on OHOS (implements local_auth).
local_auth_ohos: ^1.0.0
# Auth-key login web view on OHOS (implements webview_flutter).
webview_flutter_ohos: ^3.15.0

dev_dependencies:
flutter_test:
sdk: flutter
Expand Down
22 changes: 22 additions & 0 deletions pubspec_overrides.ohos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# OHOS-only plugin overlay — merged into pubspec.yaml by
# scripts/enable-ohos-plugins.sh before a HarmonyOS build, and NOT committed
# into the main pubspec.yaml, because these ports pin `sdk: <3.0.0` on every
# published version and cannot pass version solving under the stock Dart 3
# SDK used by CI.
#
# After `scripts/enable-ohos-plugins.sh apply`, run `flutter pub get` with the
# OHOS Flutter fork so these resolve. win32 is widened because file_picker_ohos
# pins win32 ^4 while package_info_plus 9.x needs win32 ^5; the widened range
# lets the solver pick one win32 5.x satisfying both (win32 is unused on
# OHOS, which only needs the file_picker_ohos native module).
#
# Still missing on OHOS (no compatible pub.dev port): record (record_ohos
# targets platform-interface v1, host record 7.x needs v2),
# flutter_secure_storage (same v1/v2 platform-interface split), camera,
# mobile_scanner, flutter_sound, photo_manager, flutter_local_notifications.
dependency_overrides:
package_info_plus_ohos: 0.0.7
permission_handler_ohos: 0.0.8
file_picker_ohos: 1.0.1
geolocator_ohos: 0.0.3
win32: ">=4.1.3 <6.0.0"
142 changes: 142 additions & 0 deletions scripts/enable-ohos-plugins.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env bash
# enable-ohos-plugins.sh — activate the HarmonyOS plugin overlay before an
# OHOS build, and restore the stock pubspec afterwards.
#
# Why: the ohos plugin ports for package_info_plus / permission_handler /
# file_picker / geolocator / flutter_secure_storage / record declare
# `environment: sdk <3.0.0` on every published version, so they cannot sit in
# the main pubspec.yaml — stock CI (`flutter pub get`) would fail version
# solving. The Dart-3-compatible ports (see pubspec.yaml) are regular
# dependencies already; this script layers the blocked ones on top via
# dependency_overrides, which ignores the overridden packages' sdk bounds.
#
# Usage (from the repo root):
# scripts/enable-ohos-plugins.sh apply # merge overlay into pubspec.yaml
# scripts/enable-ohos-plugins.sh revert # restore pubspec.yaml and
# # pubspec.lock from their backups
#
# Safety contract (PR #272 review): the operation is transactional on the two
# files `flutter pub get` rewrites — pubspec.yaml and pubspec.lock.
#
# apply refuses to run when an overlay is already active (a backup exists)
# or when a backup would be overwritten, so repeated apply is a
# no-op refusal, never a loss of the pre-overlay original.
# revert refuses to run when no apply is active, so it can never
# `git checkout` away a pubspec.yaml the user had edited but not
# committed. It restores the exact bytes of both files, including
# uncommitted local edits present at apply time.
#
# Neither command edits any other tracked file, and the script never
# resets, checks out or discards user files. Run with the OHOS Flutter
# fork's `flutter` on PATH, then `flutter pub get` before building; run
# `revert` before switching back to stock builds.
set -euo pipefail

cd "$(dirname "$0")/.."
OVERLAY="pubspec_overrides.ohos.yaml"
TARGET="pubspec.yaml"
LOCK="pubspec.lock"
BACKUP="pubspec.yaml.ohos-backup"
LOCK_BACKUP="pubspec.lock.ohos-backup"

die() { echo "enable-ohos-plugins: $*" >&2; exit 1; }

cmd="${1:-}"
case "$cmd" in
apply|revert) ;;
*) echo "usage: $0 apply|revert" >&2; exit 2 ;;
esac

if [[ "$cmd" == "revert" ]]; then
[[ -f "$BACKUP" ]] || die "no active overlay to revert (no $BACKUP). Refusing to touch $TARGET so uncommitted edits are not lost; restore it manually if you really meant to."
[[ ! -f "$LOCK_BACKUP" || -f "$LOCK" ]] || die "expected $LOCK with a pending $LOCK_BACKUP"
mv -f "$BACKUP" "$TARGET"
if [[ -f "$LOCK_BACKUP" ]]; then
mv -f "$LOCK_BACKUP" "$LOCK"
else
# The original had no lockfile (the backup's absence records that), so a
# lock that OHOS pub get created during the overlay must not survive the
# revert either: restore absence as well as content.
rm -f "$LOCK"
fi
echo "restored $TARGET and $LOCK from backups"
exit 0
fi

# apply: refuse unsafe states instead of discarding work.
[[ -f "$OVERLAY" ]] || die "overlay $OVERLAY not found"
[[ -f "$BACKUP" ]] && die "overlay already active ($BACKUP exists). Run revert first; refusing to overwrite the only backup of the original pubspec."
[[ -f "$LOCK_BACKUP" ]] && die "stale $LOCK_BACKUP left behind. Run revert or remove it manually first."
[[ -f "$TARGET" ]] || die "$TARGET not found"

python3 - "$TARGET" "$OVERLAY" "$BACKUP" "$LOCK" "$LOCK_BACKUP" <<'PY'
import shutil
import sys

target, overlay, backup, lock, lock_backup = sys.argv[1:6]
t_text = open(target).read()
o_lines = open(overlay).read().splitlines()

# Scalar "key: value" entries under the overlay's dependency_overrides section.
ovr, section = {}, None
for raw in o_lines:
if not raw.strip() or raw.lstrip().startswith("#"):
continue
if not raw.startswith((" ", "\t")):
section = raw.rstrip(":").strip() if raw.rstrip().endswith(":") else None
continue
if section == "dependency_overrides" and ":" in raw:
key, _, val = raw.strip().partition(":")
ovr.setdefault(key.strip(), val.strip())

# Back up the exact original bytes of both files pub get rewrites: the
# YAML is copied byte-for-byte (newline style included), never re-encoded
# through text mode, so a dirty CRLF file restores byte-identically.
with open(target, "rb") as f:
t_bytes = f.read()
with open(backup, "wb") as f:
f.write(t_bytes)
try:
shutil.copy2(lock, lock_backup)
except FileNotFoundError:
pass # pub get has not run yet; revert then leaves the lock absent too.

t_lines = t_text.splitlines()

# Split pubspec.yaml into pre / overrides-body / post around the block.
pre, body, post = [], [], []
state = "pre"
for l in t_lines:
if state == "pre":
if l == "dependency_overrides:":
state = "body"
continue
pre.append(l)
elif state == "body":
if l and not l[0].isspace():
state = "post"
post.append(l)
else:
body.append(l)
else:
post.append(l)

# Keep existing body lines except scalar keys the overlay re-defines.
body_kept = [
l for l in body
if not (l.strip() and not l.strip().startswith("#")
and l.strip().partition(":")[0].strip() in ovr)
]
appended = [f" {k}: {v}" for k, v in ovr.items()]

final = pre + ["dependency_overrides:"] + body_kept + appended
final.append("")
final += post

open(target, "w").write("\n".join(final).rstrip("\n") + "\n")
print(f"merged {len(appended)} overrides into {target} (backups: {backup}, {lock_backup})")
PY

# The backups and a lockfile rewritten for OHOS must never be committed; the
# committed ignore entries (/pubspec.yaml.ohos-backup,
# /pubspec.lock.ohos-backup) keep them out of the working copy's status.
Loading
Loading