FoxSensei001/LoveIwara
Love Iwara (i-iwara 或 2i)。一个非官方的 Iwara Flutter 应用 - 支持多个平台和设备,包括手机、平板和计算机。兼容 Android、Meta Horizon OS、Windows 等系统。
- Stars
- 1436
- Forks
- 55
- 最近推送(UTC)
- 2026年9月18日
- 项目状态
- 未归档
技术话题
使用的依赖
依赖清单 81 项
- flutter
{"sdk":"flutter"} - flutter_localizations
{"sdk":"flutter"} - get
^5.0.0-release-candidate-9.2.1 - go_router
^17.5.0 - window_manager
^0.5.0 - screen_retriever
^0.2.0 - crypto
^3.0.6 - cryptography
^2.7.0 - win32
^5.14.0 - win32_registry
^2.1.0 - logger
^2.5.0 - flutter_secure_storage
^10.0.0 - get_storage
^2.1.1 - cached_network_image
^3.4.1 - flutter_cache_manager
^3.4.2 - shimmer
^3.0.0 - extended_nested_scroll_view
^6.2.1 - markdown_widget
^2.3.2+8 - url_launcher
^6.3.1 - flutter_animate
^4.5.2 - photo_view
^0.15.0 - flutter_svg
^2.2.1 - super_clipboard
^0.9.1 - file_selector
^1.0.3 - sqlite3
^3.1.6 - sqlite3_flutter_libs
^0.6.0+eol - path_provider
^2.1.5 - path
^1.9.1 - xml
^6.6.1 - loading_more_list
^7.1.0 - waterfall_flow
^3.1.1 - share_plus
^12.0.1 - slang
4.12.1 - slang_flutter
4.12.1 - dynamic_color
^1.7.0 - toastification
^3.2.0 - app_links
^7.0.0 - floating
^6.0.0 - flutter_file_dialog
^3.0.2 - permission_handler
^12.0.1 - visibility_detector
^0.4.0+2 - yaml
^3.1.3 - screen_brightness
^2.1.4 - android_intent_plus
^6.0.0 - flutter_displaymode
^0.7.0 - qr_flutter
^4.1.0 - open_file
^4.0.0 - flutter_colorpicker
^1.1.0 - archive
^4.0.9 - ffi
^2.2.0 - volume_controller
^3.4.1 - battery_plus
^7.0.0 - uuid
^4.5.3 - extended_text_field
^17.0.0 - dlna_dart
^0.1.0 - tutorial_coach_mark
^1.3.1 - connectivity_plus
7.0.0 - network_info_plus
^7.0.0 - media_kit
^1.2.6 - media_kit_video
^2.0.1 - media_kit_libs_video
^1.0.7 - dio
^5.9.1 - cookie_jar
^4.0.8 - dio_cookie_manager
^3.3.0 - cloudflare_interceptor
^0.0.3 - html
^0.15.6 - desktop_drop
^0.7.0 - device_info_plus
^11.5.0 - dartantic_ai
^3.4.1 - flutter_local_notifications
^22.0.1 - local_notifier
^0.1.6 - liquid_glass_easy
4.1.1 - liquid_glass_widgets
^0.30.2 - local_auth
^3.0.2 - local_auth_android
^2.0.8 - flutter_test开发依赖
{"sdk":"flutter"} - slang_build_runner开发依赖
4.12.1 - build_runner开发依赖
^2.11.1 - flutter_launcher_icons开发依赖
^0.14.3 - flutter_lints开发依赖
^6.0.0 - change_app_package_name开发依赖
^1.4.0
所在榜单
原始 README
以下为英文项目原文快照,最新内容请访问 GitHub。
展开 / 收起项目 README
Love Iwara (2i)
A fast, beautiful, cross-platform third-party Iwara client built with Flutter.
One codebase → Android · Meta Quest · Windows · macOS · Linux · iOS
Telegram Group GitHub stars GitHub forks Latest release Downloads License: MIT GitHub issues
Flutter Dart Android Meta Quest Windows macOS Linux iOS
English · 日本語 · 简体中文 · 繁體中文 · 한국어 · ภาษาไทย · Bahasa Indonesia · Tiếng Việt · Español · Русский · Français · Deutsch
🌟 Introduction
Love Iwara (also known as i_iwara or 2i) is a third-party client for Iwara built with Flutter. It aims to deliver a smooth, native-feeling experience across phones, tablets, and desktops — all from a single codebase covering Android, Meta Quest, Windows, macOS, Linux, and iOS.
[!NOTE] This started as a learning project — my first attempt at a cross-platform Flutter app. Some code may not be perfectly polished, but it's actively maintained and packed with features. If you're learning Flutter too, I hope we can grow together. PRs and feedback are always welcome!
[!IMPORTANT] Usage restrictions — This project is for learning and personal reference only and is not recommended for production use. Promotion of this project on any public platform is strictly prohibited. Violations may result in maintenance being halted and the repository being removed.
[!WARNING] Disclaimer — The developer(s) have no affiliation with Iwara or its content providers. This application hosts zero content of its own.
✨ Features
🖥️ Platforms
| Android | Meta Quest | Windows | macOS | Linux | iOS |
|---|---|---|---|---|---|
| ✅ | ✅ separate APK¹ | ✅ | ✅ | ⚠️ untested² | ✅ |
¹ The Quest build is its own arm64 APK for Horizon OS (Android 14+) carrying the Meta Spatial SDK — see Meta Quest / VR. The regular Android APK is unaffected and still supports Android 7.0+. ² Linux builds are produced but currently untested due to a lack of test devices.
🎥 Video
- Smooth playback powered by media_kit (libmpv)
- Quality selection · playback-speed control (incl. a default / auto speed) · fullscreen
- Seek preview thumbnails on progress-bar hover & drag
- Clickable timestamps — jump straight to a moment from highlighted timestamps in descriptions & comments
- "Continue watching" drawer + optional auto-play on entering a video
- Live loading-speed indicator
- Panorama viewer on flat screens — a VR180 / 360° file otherwise shows up as two squashed halves; here you get a correctly proportioned viewport you can drag to look around. Iwara's files carry no spherical metadata at all, so the format is guessed heuristically — correct it by hand and the correction is remembered for that video
- "View distance" — press and hold to push the picture away or pull it closer (image zoom for flat video, field of view for panoramic)
- Open in another app — hand the current video to MX Player / VLC, to a VR player such as Skybox or Pigasus, or to a custom external player on desktop; prefers a local or already-downloaded file, with "copy link" as a fallback
- Desktop: drag & drop local video files onto the window to play instantly
🥽 Meta Quest / VR
Shipped as a separate quest APK built on the Meta Spatial SDK. The regular Android build links none of it and keeps its minSdk where it is.
The app lives in a spatial environment. Launching from the Quest home drops you straight into a resident immersive space. The entire app — browsing, search, comments, the soft keyboard — floats in front of you as a 2D panel; nothing about it is cut down. The panel is gently curved (a 30° arc — about a "3000R" monitor at its default 1.6 m width). It's the arc that's fixed, not the radius, so the curve looks the same however wide or narrow you drag the window.
Three windows, one set of gestures. The app panel, the screen and the control panel each carry their own frame: the grip trigger drags a window by its body, the edges drag and the corners resize it around its centre, and windows keep facing you. Sizes and positions are remembered. Nothing appears until head tracking has settled — no window flashing up in the wrong place and then jumping.
The player becomes a screen in the space. Open a video and it hands off automatically (optional).
- Screen shape — flat, or three degrees of curvature. Distance, width and aspect are adjustable and are remembered per aspect ratio, so returning to a 4:3 clip restores the layout you set for 4:3.
- Video formats — 2D / 3D, half & full side-by-side, half & full over-under, 180° and 360° equirect; auto-detected from the file and correctable by hand. EAC and fisheye are recognised, labelled unsupported, and offered to an external player instead.
- Playback — 0.5×–3.0× speed, loop, volume, a scrub preview showing target time and delta, a buffering indicator on the screen itself, plus clock and battery on the panel.
- "Continue watching", inside the space — the same sectioned video pools as the 2D app (source list, subscriptions, playlists, favourites, downloads, watch later), with covers. Switch videos without leaving the space; the panel shows a loading state and puts the old video back if the next one fails to load.
- Expiring links are handled — sources are refreshed before they expire, and a mid-playback 404 triggers a refresh and resumes from where you were.
- Scenes — passthrough, or a void.
Spatial gallery. A gallery opens as one large stage plus a film strip, so a set of dozens of images — and the videos mixed in among them — stays a single object rather than dozens of layers. Slideshow at 3 / 5 / 10 / 20 s, standard or original quality, and a sideways drag on the stage to flip. Portrait images are fitted into a 16:9 box so a 9:16 illustration doesn't tower over you.
Hands or controllers.
- Hands — the official ray and pinch. A pinch anywhere off the panels toggles the control panel.
- Controllers — A/X play-pause, B/Y dismisses the panel or returns to the app, Menu opens settings. The grip trigger grabs the screen without having to aim at it. The stick scrubs left/right with acceleration (a nudge is 5 s; hold and it builds up to 15 minutes per second) and pushes the screen nearer or further up/down.
- Taking the headset off pauses playback and putting it back on resumes it; a system recenter re-places everything in front of you.
A first run starts with a lesson. The headset's first-time guide isn't the touchscreen one ("pinch to zoom, hold for speed") carried over — there's no touchable picture in the space. Instead there are two courses, spatial video and spatial gallery: a controller illustration animates frame by frame along with its buttons and stick, the screen, panels and rays sit at their real geometry, and every move is shown for controllers and for bare hands. With the system's "reduce motion" on it draws a single informative still frame instead. Replayable any time from settings.
🌐 Browse & Discover
- Multi-category search: videos · galleries · posts · users · forums
- Site switching between
iwara.tvandiwara.aiat runtime - News feed integration (
news.iwara.tv) - Oreno3d tag source integration for richer video tagging
- Subscriptions, rich filtering, and responsive layouts for desktop/tablet
🖼️ Gallery
- Image browsing with smooth zoom & pan
- Gallery viewer with quality settings
💬 Community
- Forum: create & edit threads and replies
- Posts: browse & comment
- Comments: browse & reply
- Private messages: browse & reply
- In-app notifications: browse & reply
👤 Account & Sharing
- User authentication, profile management, following system
- Share videos / galleries / posts / threads / users
- Android deep-link handoff: opening an Iwara link in another app jumps back into 2i
🗂️ Local Data & Utilities
- History (local): videos · galleries · posts · forums
- Local favorites with custom favorite folders
- Downloads (beta): videos / galleries / single files, with custom paths (incl. external SD/TF card on Android)
- Backup & restore: export / import configuration and history
- Translation of descriptions, posts, comments, forums, conversations, and more
- App lock with PIN / biometrics
- "Remember last volume" option (PC)
🌍 Multi-language
12 UI languages — English · 简体中文 · 繁體中文 · 日本語 · 한국어 · ภาษาไทย · Bahasa Indonesia · Tiếng Việt · Español · Русский · Français · Deutsch — including the spatial panels on Quest, which follow the app's language rather than the system's. Iwara/Oreno3d tag names are translated for a smaller set of these languages — see below.
Found something else? There are more hidden gems to discover — and more on the way. Got an idea? Open an Issue or drop by the Telegram group.
🗺️ Roadmap
Quest support has landed — see Meta Quest / VR above. It ships as its own APK, produced by its own CI job, and the regular Android build is untouched.
Still open on the headset side:
- The GPU-memory release path for spatial panels is not yet effective.
- The spatial scene shares the main thread with Flutter; the frame cost of that has never been measured.
- The app panel is Activity-based and should migrate to a View-based panel, which the official guidance calls the lighter of the two.
- EAC and fisheye projections are detected but handed off to an external player rather than rendered.
Elsewhere: downloads are still marked beta, and Linux is built but untested for want of a test machine.
Got a request? Open an Issue or drop by the Telegram group.
🧰 Tech Stack
| Area | Library |
|---|---|
| Framework | Flutter + Dart |
| State management | GetX (get) |
| Routing | go_router |
| Networking | Dio (+ CookieJar / Cloudflare interceptors) |
| Video | media_kit (libmpv) |
| Persistence | sqlite3 · get_storage · flutter_secure_storage |
| i18n | slang |
| Desktop shell | window_manager (custom title bar, drag & drop) |
📸 Screenshots
🥽 Meta Quest
| The screen and its control panel | A gallery: one stage plus a film strip |
|---|---|
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/vr_video.jpg | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/gallery_quest.jpg |
📱 Phone & Desktop
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/home_screen.png | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/forum_page.png |
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/gallery.png | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/gallery_detail.png |
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/local_page.png | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/search_page.png |
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/search_result_page.png | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/settings_page.png |
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/sub_page.png | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/thread_detail.png |
| https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/user_detail_page.png | https://raw.githubusercontent.com/FoxSensei001/LoveIwara/HEAD/docs/imgs/video_detail.png |
🚀 Quick Start
# 1. Clone
git clone https://github.com/FoxSensei001/LoveIwara.git
cd LoveIwara
# 2. Verify your toolchain
flutter doctor
# 3. Install dependencies
flutter pub get
# 4. Run (auto-selects a connected device)
flutter run --flavor standard # Android requires a flavor — see the note below
# …or target a platform (desktop/iOS need no flavor):
flutter run -d windows # macos / linux / ios
[!IMPORTANT] Android ships two product flavors.
standardis the regular phone/tablet build (minSdk 24, all ABIs);questis the Meta Quest / Horizon OS build (minSdk 34, arm64 only, bundles the ~50 MB Meta Spatial SDK). Once flavors exist, AGP no longer has a "no flavor" variant, so every Androidflutter run/flutter buildmust pass--flavor— a bare command fails outright.
[!TIP] After editing any
lib/i18n/*.i18n.yaml, regenerate the localization strings withdart run slang. Seepubspec.yamlfor the full dependency list — a few packages need extra setup steps.
🛠️ Full development environment setup
Prerequisites
- Flutter SDK (latest stable recommended) · Dart SDK · Git
- Recommended IDE: Android Studio / VS Code / Cursor + Flutter plugin
Platform-specific requirements
Windows
- Windows 10+ (64-bit), Visual Studio 2022+, Windows 10 SDK
flutter doctor -v
macOS
- Latest macOS + Xcode + CocoaPods
sudo gem install cocoapods
Linux
# Ubuntu/Debian
sudo apt-get install clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev
# Fedora
sudo dnf install clang cmake ninja-build gtk3-devel
Android — Android Studio + Android SDK + emulator/device iOS — Xcode + simulator/device + Apple Developer account (for publishing)
Build release binaries
flutter build apk --release --flavor standard # Android APK (phones / tablets)
flutter build appbundle --release --flavor standard # Android AAB
flutter build apk --release --flavor quest --target-platform android-arm64 # Meta Quest APK
flutter build ios --release # iOS
flutter build windows --release # Windows
flutter build macos --release # macOS
flutter build linux --release # Linux
Handy commands
dart run slang # regenerate i18n strings
flutter analyze # lint
flutter test # run tests
flutter clean # clear build cache
flutter devices # list connected devices
Troubleshooting
# Dependency conflicts
flutter pub cache repair && flutter clean && flutter pub get
# Emulator
flutter emulators && flutter emulators --launch <emulator_id>
🔐 Android signing configuration
To build a signed release APK:
1. Generate a keystore (run inside android/app):
keytool -genkeypair -v -keystore keystore.jks -alias <your_key_alias> -keyalg RSA -keysize 2048 -validity 10000
Make sure keystore.jks ends up in android/app.
2. Configure signing in android/app/build.gradle:
signingConfigs {
release {
storeFile file("keystore.jks")
storePassword System.getenv("KEYSTORE_PASSWORD") ?: project.findProperty("MY_KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS") ?: project.findProperty("MY_KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD") ?: project.findProperty("MY_KEY_PASSWORD")
}
}
And add the placeholders to android/gradle.properties:
MY_KEYSTORE_PASSWORD=${KEYSTORE_PASSWORD}
MY_KEY_ALIAS=${KEY_ALIAS}
MY_KEY_PASSWORD=${KEY_PASSWORD}
3. GitHub Actions — add repository Secrets: KEYSTORE_BASE64 (base64 of keystore.jks), KEYSTORE_PASSWORD, KEY_ALIAS, KEY_PASSWORD. Then in .github/workflows/build.yml:
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
steps:
- name: Setup Keystore
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/app/keystore.jks
shell: bash
4. Build — flutter build apk --release --flavor standard → output at build/app/outputs/flutter-apk/app-standard-release.apk. For the Quest build, flutter build apk --release --flavor quest --target-platform android-arm64 → app-arm64-v8a-quest-release.apk.
🌍 Internationalization
The UI now ships in 12 languages; translations are mostly machine-generated except for the original four (English / 简体中文 / 繁體中文 / 日本語), which are human-reviewed. If you'd like to help improve a translation, start from the Simplified Chinese template: lib/i18n/zh-CN.i18n.yaml, then run dart run slang. See docs/i18n/README.md for the full per-language status and maintenance commands.
🏷️ Iwara Tag Localization
Iwara's raw tags are English-ish keys (e.g. mother, blue_archive). The app ships a community-maintained dictionary that maps every tag to Simplified Chinese / Traditional Chinese / Japanese / English, so tags render in your current language across detail pages, search, and the tag list page.
How it works:
- Dictionary: lives in
tool/data/iwara_tags/. The app consumes the merged, minifiediwara_tags.min.json. - Delivery: bundled as an offline fallback (
assets/data/iwara_tags.min.json) and hot-updated from the jsDelivr CDN — so wording can improve without shipping a new app build. - In the app: tag chips show the localized name. On a detail-page tag card, the expand/collapse row has an icon button to toggle original key ⇄ translation; long-press / right-click a tag (or tap the tag title on the tag list page) opens a dialog with both the translation and the original key, copy buttons, and a feedback link.
These are best-effort translations of 2600+ ACG / Vtuber / NSFW terms and may contain mistakes.
Spotted a wrong or awkward translation? Please report it on the dedicated issue: https://github.com/FoxSensei001/LoveIwara/issues/98 (the in-app tag dialog links here too).
Contributing a fix (for maintainers/contributors):
- Edit the human-readable
iwara_tags_localized.json(per-tagzh-CN/zh-TW/ja/en). - Regenerate the merged artifact and bundled asset:
dart run tool/data/iwara_tags/build_localized_min.dart. - Commit both the source and the generated
iwara_tags.min.json(seetool/data/iwara_tags/README.md).
The third-party Oreno3d metadata (origins / characters / tags) is localized the same way — dictionary in tool/data/oreno3d_tags/, bundled asset + jsDelivr CDN, shown in your current language on the video detail page and search cards.
[!NOTE] Both tag dictionaries above are maintained for zh-CN / zh-TW / ja / en only — they are not extended to the other 8 UI languages (ko / th / id / vi / es / ru / fr / de). These are 2600+ ACG / Vtuber / doujin-slang terms that lean on subculture-specific phrasing rather than literal translation; scaling AI translation to 12 languages without anyone able to review the result risks silently-wrong tags nobody catches. In UI languages outside those four, tags aren't translated into that language — they fall back to the dictionary's English name instead (e.g.
mother→Mother). Only a tag missing from the dictionary entirely falls back to its raw key, and that happens regardless of UI language. Details and rationale:docs/i18n/README.md.
🙏 Acknowledgments
This project drew inspiration and learned many best practices from these excellent repositories:
|
iwrqk/iwrqk
iwrqk/iwrqk Excellent Flutter-implemented Iwara client |
wgh136/PicaComic
wgh136/PicaComic Well-structured Flutter comic application |
Contributors
Thanks to everyone who has contributed! 🎉
Made with contrib.rocks
🤝 Contributing
Pull requests are welcome! For major changes, please open an issue first to discuss what you'd like to change. Before reporting a new issue, check the existing issues. Questions? Join our Telegram group.
💬 Community
Join us on Telegram: Click here to join the group.