RainBowT
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Intro ![CleanShot 2025-01-04 at 14.50.30](https://hackmd.io/_uploads/BJiH588Iyl.png) Dark Or Light Model ![CleanShot 2025-01-04 at 14.51.15](https://hackmd.io/_uploads/SJCD58IL1g.png) Sign Up Or Sign In ![CleanShot 2025-01-04 at 14.52.12](https://hackmd.io/_uploads/HkPjcUU81e.png) Register ![CleanShot 2025-01-04 at 14.52.29](https://hackmd.io/_uploads/rJK25U8Lyx.png) Sign In ![CleanShot 2025-01-04 at 14.52.41](https://hackmd.io/_uploads/B1HacIL81g.png) Home ![CleanShot 2025-01-04 at 14.54.19](https://hackmd.io/_uploads/Bku7i8U81g.png) Player ![CleanShot 2025-01-04 at 14.59.45](https://hackmd.io/_uploads/BkRP38UUye.png) Profile ![CleanShot 2025-01-04 at 15.04.22](https://hackmd.io/_uploads/ryvY688U1l.png) # Into ![Flutter Guys - Spotify](https://hackmd.io/_uploads/SJXW0I8I1l.jpg) - 學習在實際項目中應用 Clean Architecture。 - 使用 BLoC(尤其是 Qubit)進行狀態管理,深入掌握 BLoC 的運用。 - 遵循依賴反轉原則,並使用 Get It 作為依賴注入工具,簡化專案複雜度。 - 使用 Dart 的錯誤處理機制。 - Firebase 的 Firestore、Storage 和 Authentication 完整應用。 - 使用 Just Audio 播放音樂。 - 項目設計包括登入/註冊頁面、明暗主題切換、歌曲顯示、收藏頁面等。 # Design - 使用 Figma 設計應用介面,包括登入/註冊頁、明暗主題切換、主要頁面等。 - 配色和設計以提高使用者體驗為主。 # Project Structure - Clean Architecture 分為三層:Domain、Data 和 Presentation。 - 各層結構如下: - **Presentation**: 包括 BLoC、Page 和 Widgets。 - **Domain**: 包括 Entities、Repository 和 Use Cases。 - **Data**: 包括 Data Sources、Repository Implementation 和 Models。 - 額外建立 Core 和 Common 文件夾以管理共用邏輯和設定。 # Theme Of Application - 在 Core 資料夾內創建 Configs 資料夾以管理主題、樣式和本地化設定。 - 使用 AppColors 類別定義主要顏色,包括主色、背景色(明暗主題)和其他常用顏色。 - 創建 AppTheme 類別,定義明暗主題設定(如主要顏色、背景色、按鈕樣式、字型等)。 # Assets / Fonts - 在專案根目錄下創建 Assets 資料夾,包括 Fonts、Images 和 Vectors。 - 將字型檔案放入 Fonts 資料夾並在 pubspec.yaml 中定義資源路徑。 - 設定字型權重以便於在專案中呼叫不同字重。 - 在主題中應用自定義字型。 # Splash Page - 在 Presentation 層創建 Splash 資料夾,內含 BLoC、Page 和 Widgets。 - 建立 SplashPage 類別作為啟動畫面。 - 使用 SVG Picture 顯示 SVG 格式的應用標誌,並透過資源管理類別集中管理資源路徑。 - 隱藏 Debug Banner 並設置預設的首頁為 SplashPage。 # Get Started Page ## 實作 Splash Page 的導向功能 - 將 StatelessWidget 轉為 StatefulWidget,以使用 `initState` 方法。 - 在 `initState` 中建立 `redirect` 函式,使用 `Future.delayed` 設定 2 秒延遲,並透過 `Navigator.pushReplacement` 導向到 Get Started Page。 - 呼叫 `redirect` 函式。 ## 建立 Get Started Page - 新增 `intro/pages/get_started_page.dart` 檔案,定義 `GetStartedPage` 為 StatelessWidget。 - 在 `build` 方法中加入 `Scaffold`,並設定其內容為 `Stack`。 ## 顯示背景圖片 ![CleanShot 2024-11-29 at 04.59.58](https://hackmd.io/_uploads/SJsRKUUmkg.png) - 匯入圖片至 `assets/images` 資料夾,命名為 `intro_background.png`。 - 建立 `configs/app_images.dart` 定義 `AppImages` 類別,宣告靜態常數 `introBackground` 作為圖片路徑。 - 在 `GetStartedPage` 使用 `BoxDecoration` 和 `DecorationImage` 顯示背景圖片,並設定 `fit` 為 `BoxFit.cover`。 ## 加入黑色透明遮罩 - 在背景圖片上方新增 `Container`,設定 `color` 為黑色,透明度設為 0.15。 ## 顯示 Spotify Logo 與文字 ![CleanShot 2024-11-29 at 05.12.38](https://hackmd.io/_uploads/BysAn88Q1e.png) - 使用 `SVGPicture.asset` 顯示 Spotify Logo,並用 `Align` 設定對齊至上方中央。 - 使用兩個 `Text` 元件顯示文字,分別設定不同樣式: - 第一段文字:字重 `FontWeight.bold`,字體大小 `18`,顏色為白色。 - 第二段文字:字重 `FontWeight.w500`,字體大小 `13`,顏色為灰色。 - 用 `SizedBox` 調整文字之間的間距。 ## 加入按鈕元件 ![CleanShot 2024-11-29 at 05.28.29](https://hackmd.io/_uploads/r1FYxPUXJe.png) - 在 `widgets/button/basic_app_button.dart` 中建立通用按鈕元件 `BasicAppButton`,使用 `ElevatedButton`。 - 提供參數 `onPressed`、`title`,並新增可選參數 `height`(預設為 80)。 - 在 `GetStartedPage` 中使用 `BasicAppButton` 顯示按鈕,設定標題為 "Get Started",並使用 `SizedBox` 調整按鈕與文字間距。 ## 優化與調整 ![CleanShot 2024-11-29 at 05.29.37](https://hackmd.io/_uploads/SJRReDL7Jl.png) - 使用 `const` 關鍵字優化元件以減少重建。 - 修正警告訊息並保持程式碼整潔。 # Choose Light-Dark Mode Page ![CleanShot 2024-12-16 at 14.37.08](https://hackmd.io/_uploads/rJEnqSTV1l.png) ## 建立選擇模式頁面 (Choose Mode Page) - 新增資料夾 `choose_mode` 並建立 `page/choose_mode.dart` 文件。 - 建立 `ChooseModePage` 類別,返回 Scaffold 結構。 ## 導航到選擇模式頁面 - 在「Get Started」按鈕點擊事件中使用 `Navigator.push`,透過 `MaterialPageRoute` 導航到 `ChooseModePage`。 - 修正按鈕點擊失效問題,將覆蓋按鈕的容器移到 `Stack` 結構的底層。 ## 設計選擇模式頁面 - 匯出背景圖片並存入 `assets/images` 資料夾。 - 在資產管理類別中定義靜態常數 `chooseModeBackground`。 - 從 Get Started 頁面複製結構,修改背景圖片為 `chooseModeBackground`。 - 修改標題文字為 "Choose Mode",增加按鈕間距,移除多餘文字,新增兩個按鈕。 ## 圖示與樣式設定 - 匯出太陽與月亮圖示,並在向量管理類別中定義靜態常數 `sun` 和 `moon`。 - 為按鈕新增圓形容器,使用 `BoxDecoration` 設定形狀與顏色。 - 加入背景模糊效果,使用 `BackdropFilter` 搭配 `ImageFilter.blur`。 - 中心加入圖示,透過 `SvgPicture.asset` 顯示。 - 下方加入文字標籤,設定字體樣式與顏色。 ## 初始化主題切換邏輯 - 新增 `flutter_bloc`、`hydrated_bloc` 和 `path_provider` 至 `pubspec.yaml`。 - 在 `main.dart` 初始化 `HydratedBloc`,設定存儲目錄。 - 建立 `ThemeCubit` 類別,繼承 `HydratedCubit` 並管理 `ThemeMode` 狀態。 - 實作方法 `updateTheme` 用於切換主題。 ## 主題切換邏輯整合 - 在 `main.dart` 使用 `MultiBlocProvider` 注入 `ThemeCubit`。 - 用 `BlocBuilder` 監聽主題變化並更新 `MaterialApp` 的 `themeMode`。 - 在選擇模式頁面,將按鈕包裝為 `GestureDetector`,使用 `context.read<ThemeCubit>().updateTheme()` 切換主題。 ## 測試與調整 - 點擊按鈕切換主題後,應保存主題設定並在應用程式重新啟動後生效。 - 目前缺少顯示選擇狀態的設計,但基本主題切換邏輯已完成。 # Logic Of Light-Dark Mode ![CleanShot 2024-12-25 at 21.38.58](https://hackmd.io/_uploads/HyaZjKFrJx.png) ## 初始化 `hydrated_bloc` 和依賴套件 - 使用 `hydrated_bloc` 儲存主題模式,不需 `shared_preferences`。 - 添加 `flutter_bloc`、`hydrated_bloc` 和 `path_provider` 套件。 - 將套件加入 `pubspec.yaml` 並執行下載。 ## 初始化 `hydrated_bloc` 在主檔案 - 在 `main.dart` 初始化 `hydrated_bloc`。 - 匯入 `hydrated_bloc`、`foundation` 和 `path_provider`。 - 修改代碼中的 `App` 為 `MyApp` 並添加必要的 `const`。 ## 建立 Theme Cubit - 在 `presentation` 資料夾中新增 `bloc` 資料夾與 `theme_cubit.dart` 檔案。 - 建立 `ThemeCubit` 類別,繼承 `HydratedCubit<ThemeMode>`。 - 定義初始狀態為 `ThemeMode.system`。 - 建立 `updateTheme` 方法,接受 `ThemeMode` 參數並發出狀態。 ## 設置 MultiBlocProvider - 在 `main.dart` 使用 `MultiBlocProvider` 包裹 `MaterialApp`。 - 注入 `ThemeCubit`,以監聽主題模式的變更。 - 使用 `BlocBuilder` 包裹 `MaterialApp`,根據主題模式設定 `theme` 和 `darkTheme`。 ## 修改選擇模式頁面 - 在選擇模式頁面,將容器包裹在 `GestureDetector` 中。 - 使用 `context.read<ThemeCubit>().updateTheme` 呼叫 `updateTheme` 方法。 - 為不同的容器傳遞 `ThemeMode.light` 和 `ThemeMode.dark`,以切換主題模式。 - 測試功能確認主題模式切換是否正常工作。 # SigninOr Signup Page ![CleanShot 2024-12-26 at 10.05.55](https://hackmd.io/_uploads/B1_G54cSkg.png) ## 實作登入與註冊頁面 - 根據設計,首先需要實作登入或註冊頁面。 - 匯出 Figma 設計圖,將圖像導出為 SVG(如頂部與底部圖案)和 PNG 格式(認證背景圖)。 - 在專案中創建 `authentication` 資料夾並新增 `sign_up_or_sign_in.dart` 檔案。 - 在頁面中使用 `Scaffold` 和 `Stack`,並使用對應的對齊來顯示設計圖案。 --- ## 設定頁面背景與圖案 - 使用 `Stack` 來實現背景圖案,並使用 `alignment` 設置圖案的位置。 - 定義靜態常數來存儲頂部與底部圖案路徑,並加載對應的 SVG 圖片。 - 設定圖片為底部和左側的背景,確保顯示正確。 --- ## 顯示應用程式內容 - 在頁面中使用 `Column` 顯示應用的內容,包括 logo、文字和按鈕。 - 使用 `SizedBox` 來設置各元素之間的間距。 - 使用 `Text` 來顯示文字,並設置對應的字體大小、顏色與間距。 - 根據設計,顯示兩個按鈕並設置相應的字體大小、顏色和間距。 --- ## 處理主題切換問題 - 針對亮暗模式,使用條件來設置文字顏色(白色或黑色)。 - 創建 `isDarkMode` 擴展函數來檢查當前的主題並返回適當的顏色。 - 在頁面中使用 `context.read<ThemeCubit>().updateTheme` 來檢查主題並設置文字顏色。 --- ## 實作回退按鈕 - 在 `widgets` 資料夾中創建 `BasicAppBar` 作為回退按鈕的共用元件。 - 設定 `AppBar` 背景色為透明,並設置回退按鈕圖標。 - 設置按鈕顏色依據暗色或亮色主題變更,並處理按下事件調用 `Navigator.pop` 返回上一頁。 --- ## 測試與調整 - 測試頁面在不同主題模式下的顯示,確保圖案與顏色切換正確。 - 測試登入和註冊頁面是否能夠正常顯示並實現功能。 # Signup Page & Signin Page ![CleanShot 2024-12-27 at 06.09.10](https://hackmd.io/_uploads/rJ-QVLsB1g.png) ## 建立註冊與登入頁面 - 建立 SignUp 和 SignIn 頁面,分別處理註冊與登入功能。 - 使用 Scaffold 作為頁面框架,透過 Column 堆疊元件。 - 設置導航邏輯,實現頁面間跳轉功能。 ## 自訂 AppBar 與樣式 - 建立 BasicAppBar 作為自訂的 AppBar 元件。 - 支援 PreferredSizeWidget 接口,設置標題與背景透明。 - 在標題中顯示 SVG Logo,支援調整大小與居中顯示。 ## 設計輸入欄位 - 建立全名、電子郵件與密碼的 TextField 輸入框。 - 使用 InputDecoration 自訂樣式,設置圓角邊框與提示文字樣式。 - 預設內容間距與邊框顏色,支援暗色與亮色主題。 ## 基本按鈕與文字連結 - 自訂按鈕樣式,實現按鈕文字與點擊事件。 - 建立文字連結,如「Sign In」和「Register Now」按鈕。 ## 暗色與亮色模式支援 - 根據主題動態調整元件顏色,如文字與按鈕背景。 - 在暗色與亮色主題中分別設置輸入框與提示文字的樣式。 ## 頁面間的邏輯與導航 - 使用 Navigator.push 和 Navigator.pushReplacement 管理頁面導航。 - 註冊頁面與登入頁面間相互跳轉,實現流暢的使用者體驗。 ## 優化與共用元件 - 將重複元件提取為獨立組件,提升程式碼可讀性與可維護性。 - 在共用樣式檔中設置輸入框樣式,方便統一修改設計。 # Firebase Setup & Logic Of Authentication & Service Locator ## Firebase CLI 設定 - 使用 Firebase CLI 來設定專案,建議選擇 Standalone Binary 進行安裝。 - 登入 Firebase 帳戶,使用 `firebase login` 命令,確認登入成功。 - 使用 `firebase init` 命令來初始化 Firebase 專案,選擇專案名稱和平台(Android/iOS)。 ``` dart pub global activate flutterfire_cli ``` ``` flutterfire configure ``` ## Firebase 初始設定 - 在專案的主程式檔(main.dart)中,初始化 Firebase。 - 使用 `Firebase.initializeApp` 並指定 options,從 Firebase 的 options 檔案中讀取設定。 - 確保 `firebase_core` 套件已在 `pubspec.yaml` 中添加。 ## 架構與 Domain Layer - 遵循 Clean Architecture,先從 Domain Layer 開始實作邏輯。 - 在 entities 資料夾中新增 `authentication`,建立 `user_entity` 類別。 - 定義必要的欄位(例如 fullName、email、userId)及其建構子(Constructor)。 - 在 repository 資料夾中新增 `authentication`,定義 `AuthenticationRepository` 抽象類別,包含 signUp 和 signIn 方法。 ## Data Layer 設定 - 在 Data Layer 中新增 `authentication` 資料夾,包含 models、repositories 和 sources。 - 在 models 資料夾中建立 `create_user_request` 類別,定義 fullName、email 和 password 欄位。 - 在 sources 中建立 `AuthenticationFirebaseService` 抽象類別,定義 signUp 和 signIn 方法。 - 建立 `AuthenticationFirebaseServiceImplementation` 類別,實作 Firebase 認證的邏輯,包含錯誤處理和 Firebase 的 `createUserWithEmailAndPassword` 方法。 ## 使用 Service Locator - 使用 `get_it` 套件實現依賴注入,避免手動創建實例造成代碼複雜度增加。 - 建立 `service_locator.dart`,創建一個全域的 Service Locator 實例(例如 `final sl = GetIt.instance`)。 - 定義 `initializeDependencies` 方法,註冊單例服務,如 `AuthenticationFirebaseService` 和 `AuthenticationRepository`。 - 在主程式中呼叫 `initializeDependencies`,於執行應用程式前初始化依賴。 ## Repository 實作 - 在 `data/repositories` 中建立 `AuthenticationRepositoryImplementation` 類別,實作 `AuthenticationRepository` 抽象類別的方法。 - 使用 Service Locator 訪問 `AuthenticationFirebaseService`,並調用其 signUp 和 signIn 方法。 - 使用 `CreateUserRequest` 類別封裝從使用者獲取的數據並傳遞至 Firebase 方法。 ## 錯誤處理 - 在 Firebase Service 和 Repository 中添加錯誤處理邏輯,使用 try-catch 块處理 Firebase 認證異常。 - 針對常見錯誤如無效的 email 或密碼提供用戶提示。 # UseCases Setup - Calling Signin / Signup UseCases ## 定義 Use Case 抽象類別 - 建立 `use_case` 資料夾與 `use_case.dart` 文件。 - 創建抽象類別 `UseCase`,接受泛型參數 `Type`(回傳值類型)與 `Params`(輸入參數類型)。 - 定義 `call` 方法,回傳 `Type`,接受 `Params` 作為輸入。 ## 設計 Sign Up Use Case - 在 `domain/use_cases/authentication` 中新增 `sign_up_use_case.dart`。 - 繼承 `UseCase`,設置 `Type` 為 `Either` 類別,`Params` 為 `CreateUserRequest` 類別。 - 實作 `call` 方法,呼叫 `AuthenticationRepository` 的 `signUp` 方法。 - 修改 `AuthenticationRepository` 的 `signUp` 方法回傳類型為 `Either`,在成功與失敗情況下回傳不同訊息。 ## 註冊 Sign Up Use Case - 在 Service Locator 註冊 `SignUpUseCase`。 - 確保在應用程式中可以正常調用。 ## 使用 Sign Up Use Case - 在 `presentation/authentication/sign_up_page.dart` 中實作相關功能。 - 建立 `TextEditingController` 管理使用者輸入的 `fullName`、`email` 和 `password`。 - 呼叫 `SignUpUseCase`,傳入 `CreateUserRequest`,並使用 `Either.fold` 檢查結果,成功時導向 Root 頁面,失敗時顯示錯誤訊息。 ## Firebase 設定與測試 Sign Up - 在 Firebase Console 啟用 Email/Password 註冊方式。 - 測試弱密碼與已存在的 Email 錯誤處理,確認成功時會導向 Root 頁面。 ![CleanShot 2024-12-28 at 09.02.19](https://hackmd.io/_uploads/r18BRphrke.png) ## 設計 Sign In Use Case - 新增 `sign_in_use_case.dart`,邏輯類似 `sign_up_use_case.dart`。 - 定義 `SignInUserRequest` 類別,僅包含 `email` 與 `password`。 - 修改 `AuthenticationRepository` 的 `signIn` 方法回傳類型為 `Either`,處理成功與錯誤情況。 - 錯誤類型包括無效 Email(無使用者)與無效憑證(密碼錯誤)。 ## 註冊 Sign In Use Case - 在 Service Locator 註冊 `SignInUseCase`,確保可用於應用程式中。 ## 使用 Sign In Use Case - 在 `presentation/authentication/sign_in_page.dart` 中實作相關功能。 - 建立 `TextEditingController` 管理使用者輸入的 `email` 與 `password`。 - 呼叫 `SignInUseCase`,傳入 `SignInUserRequest`,並使用 `Either.fold` 檢查結果,成功時導向 Root 頁面,失敗時顯示錯誤訊息。 ## 測試 Sign In - 測試無效 Email、密碼錯誤以及成功登入情況,確認正確導向或顯示錯誤訊息。 - ![CleanShot 2024-12-28 at 09.26.24](https://hackmd.io/_uploads/B1NkVChH1x.png) ![CleanShot 2024-12-28 at 09.27.30](https://hackmd.io/_uploads/ryvXNAhS1e.png) # Upload Songs To FireStorage & Cloud FireStore Collections & Adding Information Of User To FireStore Collection ## 已完成的功能實作 - 完成 Authentication 領域層與資料層的實作,包含 Service Locator 和 Use Case 整合。 ## Firebase Storage 設定與檔案上傳 - 開啟 Firebase Console,完成 Storage 初始化設定。 - 建立資料夾 songs 與 covers,分別上傳歌曲檔案與封面圖片。 - 測試圖片檔案 URL,移除 token 後發現無權限問題。 - 修改 Storage Rules 設定 read: true、write: false,解決無權限問題。 ## Firebase Firestore 設定與 Songs Collection 建立 - 開啟 Firebase Console,啟用 Firestore Database。 - 建立 songs 集合並新增文件,使用 Auto ID。 - 新增欄位 title、artist name、duration、release date,儲存歌曲相關資料。 ## User Collection 自動建立與 Sign-up 整合 - 新增 Firestore 依賴項,實現 users 集合自動建立。 - 在資料層的註冊功能中,透過 add 方法新增文件。 - 文件內容包含 name 和 email,從 Sign-up 表單抓取用戶輸入的名稱與郵件。 - 修正 Firestore Rules,檢查 request.auth != null,允許合法寫入操作。 - 測試結果顯示用戶資料成功寫入 users 集合,包含正確名稱與電子郵件。 # Home Page - Fetching Songs - Display Songs Using Bloc,.... ![CleanShot 2024-12-30 at 11.06.10](https://hackmd.io/_uploads/Skz8AtkUke.png) ## 建立 Cloud Firestore 集合與專案規劃 - 完成專案需實現三個頁面:首頁、音樂播放器頁面與使用者個人頁面。 - 首要任務是實作首頁。 ## 匯出資源 - 將卡片元件匯出為 SVG 格式,儲存至 `assets/vectors` 資料夾。 - 將圖像匯出為 PNG 格式,儲存至 `assets/images` 資料夾並命名為 "artist"。 ## 修改路由與首頁檔案 - 將路由檔案名稱從 `root` 改為 `home`。 - 將路由頁面從 `rootPage` 改為 `homePage`,並同步修改其他頁面設定。 ## 建立 App Bar - 從註冊或登入頁面複製 App Bar,並貼到首頁。 - 使用 `hideBack` 布林參數控制是否顯示返回按鈕,`true` 不顯示,`false` 顯示。 ## 首頁卡片元件 - 建立 `HomeTopCard` 小元件,設定卡片大小與內容。 - 使用 `SvgPicture.asset` 加載 SVG 圖像,定義靜態常量 `homeTopCard` 儲存資源路徑。 ## 使用 Stack 組合圖像與卡片 - 在卡片上方顯示圖像,使用 `Stack` 包裹 SVG 卡片與圖像。 - 定義靜態常量 `homeArtist` 儲存圖像資源路徑。 - 使用 `SizedBox` 調整卡片與圖像大小,並加上右側間距。 ## 實作 Tab Bar - 新增 `TabBar` 元件,定義四個標籤:新聞、影片、藝術家、Podcast。 - 使用 `TabController` 控制標籤,設定長度為 4。 - 將元件類型改為 `StatefulWidget`,在 `initState` 中初始化 TabController。 ## 自訂 Tab Bar 樣式 - 設定文字顏色,深色模式顯示白色文字,淺色模式顯示黑色文字。 - 增加文字粗細與字體大小,設定標籤指示器顏色為主要顏色。 - 使用 `EdgeInsets.symmetric` 設定水平與垂直間距。 --- ## 建立歌曲實體 (Song Entity) - 在 `domain/entities` 資料夾中建立 `song` 資料夾,新增 `song.dart` 文件。 - 定義歌曲實體包含以下欄位:`title`、`artist` (字串),`duration` (數字),`releaseDate` (時間戳記)。 - 為實體建立建構子。 ## 建立歌曲模型 (Song Model) - 在 `data/models` 資料夾中建立 `song` 資料夾,新增 `song.dart` 文件。 - 模型包含與實體相同的欄位,並實作 `fromJson` 方法將 JSON 轉換為模型。 - 定義擴展方法將模型轉換為實體。 ## 定義歌曲存取介面 - 在 `domain/repositories` 資料夾中建立 `song` 資料夾,新增 `song_repository.dart` 文件。 - 定義抽象類別 `SongsRepository`,包含方法 `getNewsSongs`,回傳型別為 `Either`。 ## 實作 Firebase 資料服務 - 在 `data/sources` 資料夾中建立 `songs` 資料夾,新增 `song_firebase_service.dart` 文件。 - 定義抽象類別 `SongFirebaseService`,包含方法 `getNewsSongs`。 - 實作該抽象類別,透過 Firebase Firestore 存取歌曲集合,按 `releaseDate` 遞減排序,取最新的三筆文件。 - 使用迴圈將每個文件的 JSON 資料轉換為模型,然後轉換為實體並加入列表。 ## 錯誤處理 - 將資料存取邏輯包裹於 `try-catch` 區塊中,成功時回傳 `Either.right`,錯誤時回傳 `Either.left`,並提供錯誤訊息。 ## 實作歌曲資料儲存庫 - 在 `data/repositories` 資料夾中建立 `song` 資料夾,新增 `song_repository_implementation.dart` 文件。 - 建立 `SongRepositoryImplementation` 類別,實作 `SongsRepository`。 - 在 `getNewsSongs` 方法中呼叫 `SongFirebaseService` 的實作。 ## 建立歌曲用例 (Use Case) - 在 `domain/use_cases` 資料夾中建立 `song` 資料夾,新增 `get_news_songs.dart` 文件。 - 建立 `GetNewsSongsUseCase` 類別,實作用例邏輯,調用儲存庫的 `getNewsSongs` 方法。 ## 註冊依賴注入 - 在服務定位器中註冊 `SongFirebaseService`、`SongRepositoryImplementation` 和 `GetNewsSongsUseCase`。 - 確保依賴關係正確連結並可供全域存取。 --- ## 實作 Bloc 狀態管理 - 在 `bloc` 資料夾建立 `news_songs_state.dart` 和 `news_songs_cubit.dart` 檔案。 - 定義狀態包括 `NewsSongsState`(抽象基類)、`NewsSongsLoading`(載入中)、`NewsSongsLoaded`(包含歌曲列表資料)、`NewsSongsLoadFailure`(載入失敗)。 - 在 Cubit 中實作 `getNewsSongs` 方法,呼叫用例,根據結果發送相應狀態。 ## 建立內容展示元件 - 在 `widget` 資料夾建立 `news_songs.dart`。 - 使用 `BlocProvider` 注入 `NewsSongsCubit`,在元件渲染時調用 `getNewsSongs` 方法。 - 使用 `BlocBuilder` 根據狀態渲染 UI,包括載入動畫、歌曲列表和空白容器。 ## 圖片與歌曲資訊顯示 - 使用 `Container` 與 `BoxDecoration` 顯示圖片,並設定圓角。 - 圖片 URL 根據 `artist` 和 `title` 動態生成。 - 在圖片下方展示歌曲名稱與歌手名稱,設置字體加粗與適當間距。 ## 播放按鈕設計 - 在圖片右下角使用 `Transform` 設置圓形播放按鈕。 - 按鈕顏色與應用程式主題模式(明亮或黑暗)同步。 - 在按鈕內放置播放圖示,適應應用程式配色。 ## Tab 與新聞內容整合 - 在首頁使用 `TabBarView`,將 `NewsSongs` 元件作為其中一個子頁籤。 - 為其他頁籤(例如影片、藝術家、Podcast)暫時使用空容器。 - 使用 `SizedBox` 包裹 `TabBarView` 以解決高度相關問題。 --- ## 播放清單資料處理 - 在 Repository 中新增 `getPlaylist` 方法,從 Firestore 獲取所有歌曲資料(無需限制數量)。 - 在 Use Case 資料夾中新增 `getPlaylist` 使用案例,並實現邏輯以呼叫 `getPlaylist` 方法。 - 在 Service Locator 註冊 `getPlaylist` 使用案例以便後續使用。 ## 播放清單狀態管理 - 在 Bloc 資料夾新增 `playlist_cubit.dart` 和 `playlist_state.dart`。 - 定義狀態,包括 `PlaylistLoading`(載入中)、`PlaylistLoaded`(包含歌曲列表資料)、`PlaylistLoadFailure`(載入失敗)。 - 在 Cubit 中實作 `getPlaylist` 方法,呼叫用例並根據結果發送相應狀態。 ## 播放清單元件設計 - 在 Widgets 資料夾新增 `playlist.dart`,使用 BlocProvider 注入 PlaylistCubit。 - 使用 BlocBuilder 根據 PlaylistCubit 的狀態渲染 UI,包含載入動畫和歌曲列表。 - 播放清單列表以 ListView 顯示,每個項目包含歌曲名稱、歌手名稱、播放按鈕和喜好按鈕。 ## 播放清單標題與更多按鈕 - 使用 Column 元件顯示播放清單標題與「查看更多」按鈕。 - 播放清單標題字體加粗,字號較大;「查看更多」字體較小,顏色與應用主題一致。 - 增加左右與上下間距以調整外觀。 ## 播放清單歌曲項目設計 - 使用 Row 元件佈局,包含播放按鈕、歌曲資訊和喜好按鈕。 - 播放按鈕以圓形容器顯示,背景顏色根據主題變化,內嵌播放圖示。 - 歌曲名稱字體加粗,歌手名稱字體較細,並有適當間距。 - 加入時長顯示,字體與歌曲資訊一致。 ## 喜好按鈕設計 - 使用 IconButton 作為喜好按鈕,顏色與應用程式主題一致。 - 提供基礎樣式與交互行為,喜好邏輯將於稍後實作。 ## 整合播放清單至首頁 - 在首頁新增 Playlist 區域,顯示於 TabBarView 下方。 - 播放清單區域設置適當的間距與佈局,使整體視覺效果統一。 - 測試應用程式以確認播放清單功能與外觀正常運作。 # Song Player Page - Using Bloc To Manage State Of Playing Song ![CleanShot 2025-01-01 at 20.27.37](https://hackmd.io/_uploads/SyapV3f81e.png) ## 建立 `SongPlayer` 頁面與結構 - 建立 `song_player` 資料夾,內含 `pages` 和 `block` 資料夾。 - 在 `pages` 資料夾中建立 `song_player.dart` 文件,建立 `StatelessWidget` 的 `SongPlayerPage` 類別。 - `SongPlayerPage` 使用 `Scaffold` 作為基礎結構。 ## 導航到 `SongPlayerPage` - 在首頁 (`HomePage`) 的 `new songs` 和 `playlist` 頁面,將項目包裹在 `GestureDetector` 中。 - 使用 `Navigator.push` 和 `MaterialPageRoute` 導航到 `SongPlayerPage`。 ## 添加 AppBar - 在 `SongPlayerPage` 中實作基本的 AppBar。 - 設定標題為 "Now Playing" 並調整樣式。 - 添加右側的更多選單按鈕,使用 `Icon` 和 `IconButton`。 ## 顯示歌曲封面 - 在 `SongPlayerPage` 中,傳入 `SongEntity` 對象,透過建構函數接收。 - 建立 `SongCover` 小部件,使用 `Container` 和 `NetworkImage` 顯示歌曲封面。 - 添加圖片樣式,如圓角、縮放、間距。 ## 顯示歌曲細節 - 建立 `SongDetail` 小部件,顯示歌曲名稱、藝術家名稱和喜歡按鈕。 - 調整標題字體大小,排列樣式設為 `MainAxisAlignment.spaceBetween`。 - 喜歡按鈕使用 `IconButton`,切換圖標為 `Icons.favorite_outline`。 ## 優化設計 - 在 `SingleChildScrollView` 中使用 `Column` 結構。 - 在封面與細節間添加空隙。 - 添加 `Padding` 調整頁面間距。 - 修改 `Playlist` 頁面的喜歡按鈕樣式以保持一致性。 ## Slider 和歌曲時間顯示 - 使用 Bloc 管理狀態,實時更新歌曲的播放進度。 - 在 `bloc` 資料夾新增 `SoundPlayerCubit` 和 `SoundPlayerState` 文件。 - 定義三種狀態:`loading`、`loaded`、`failure`。 - 使用 `just_audio` 庫實作歌曲播放邏輯。 ## `SoundPlayerCubit` 的實作 - 初始化 `AudioPlayer` 實例。 - 定義 `loadSong` 方法載入歌曲 URL,更新狀態為 `loaded` 或捕捉錯誤設為 `failure`。 - 定義 `playOrPauseSong` 方法,根據播放狀態呼叫 `play` 或 `pause` 方法。 - 定義 `songDuration` 和 `songPosition` 變數儲存歌曲總時長與目前位置。 - 使用 `stream` 監聽歌曲播放位置與時長,並更新 UI。 ## 在 UI 中整合 Bloc - 使用 `BlocProvider` 注入 `SoundPlayerCubit`。 - 呼叫 `loadSong` 並傳入歌曲的 URL。 - 修改 URL 格式區分封面圖與 MP3 檔案。 ## 顯示 Slider 和時間 - 建立新元件 `SongPlayer`,使用 `BlocBuilder` 更新狀態。 - 狀態為 `loading` 時顯示 `CircularProgressIndicator`,為 `loaded` 時顯示進度條。 - 使用 `Slider` 顯示播放進度,`value` 設為目前播放位置,`min` 設為 0,`max` 設為歌曲總時長。 - 顯示目前播放位置與總時長,格式化時間為 `分鐘:秒` 格式。 ## 播放/暫停按鈕 - 建立圓形按鈕,使用 `Icon` 顯示播放或暫停圖示。 - 根據播放狀態切換圖示,正在播放時顯示 `Icons.pause`,未播放時顯示 `Icons.play_arrow`。 - 使用 `GestureDetector` 包裹按鈕,實現點擊播放或暫停功能。 ## 優化設計與測試 - 修正歌曲 URL,將 `cover` 改為 `songs`。 - 重啟應用測試進度條與播放按鈕,確認功能正常。 - 測試結果:播放器功能完成,播放與暫停運作良好。 # Logic Of Favorite Songs ## Firebase 鑑權與資料結構設計 - 使用 Firebase Authentication 獲取已登入使用者的 userID - 每位使用者的文件包含子集合 favorites,存放收藏的歌曲 - 修改 signUp 流程,使用 userID 作為自訂文件 ID ## 資料庫操作與方法設計 - 在 SongRepository 中新增 addOrRemoveFavoriteSong 方法 - 在 SongFirebaseService 中覆寫該方法,實現歌曲收藏的新增或移除 - 檢查 favorites 集合中是否已有指定歌曲 ID,決定新增或刪除 - 使用 FirebaseFirestore 的 add 方法新增歌曲收藏,delete 方法刪除收藏 ## 判斷歌曲是否為收藏 - 新增 isFavoriteSong 方法,檢查指定 songID 是否存在於 favorites 集合 - 使用 where 過濾指定歌曲,返回布林值表示是否已收藏 ## 使用案例 (Use Cases) - 創建 addOrRemoveFavoriteSongUseCase 處理新增或移除收藏 - 創建 isFavoriteSongUseCase 檢查歌曲是否為收藏 - 註冊上述使用案例於服務定位器 ## 更新歌曲實體與模型 - 在歌曲實體與模型中新增屬性 isFavorite 和 songID - 在 SongFirebaseService 的 getNewSongs 和 getPlaylist 方法中設置這些屬性 ## 收藏按鈕 (Favorite Button) - 使用 Bloc 建立 FavoriteButtonCubit 處理收藏按鈕的狀態管理 - 收藏按鈕初始狀態為 FavoriteButtonInitial,狀態更新為 FavoriteButtonUpdated - 根據 isFavorite 的值顯示實心或空心收藏圖標 - 在按鈕點擊事件中調用 addOrRemoveFavoriteSongUseCase 切換收藏狀態 ## UI 組件化設計 - 將收藏按鈕封裝為通用組件,接收 songEntity 決定按鈕狀態 - 點擊按鈕觸發 updateFavoriteButton 方法處理收藏切換 - 在 Playlist 和 MusicPlayerPage 中調用該通用組件 ## Firebase 儀表板驗證 - 在 Firebase 儀表板中驗證 favorites 集合的更新 - 確認收藏按鈕觸發後,歌曲文件正確新增或移除 - 文件包含 songID 和 addedDate # User Profile Page - Display User Info -Display Favorite Songs - Remove Favorite Song ![CleanShot 2025-01-04 at 14.49.15](https://hackmd.io/_uploads/rJmZqIIUJe.png) ## 建立 Profile 頁面基本結構 - 新增 `profile` 資料夾,建立 `pages` 資料夾與 `profile.dart` 文件。 - 建立無狀態類別,回傳 `Scaffold` 作為頁面框架。 - 在首頁 `AppBar` 中加入 `IconButton`,使用 `Navigator` 導向 `Profile` 頁面。 - 使用 `Icons.person` 作為圖示。 ## Profile 頁面設計與區塊劃分 - 頁面分為使用者資訊與收藏歌曲清單兩部分。 - 使用 `AppBar`,標題設為 `Profile`,支援淺色與深色模式背景顏色。 - 頁面主體使用 `Column`,上方顯示使用者資訊,下方顯示歌曲清單。 ## 使用者資訊區塊設計 - 建立 `profileInfo` 小元件,回傳帶裝飾的 `Container`。 - 設置深色模式灰色與淺色模式白色的背景顏色。 - 加入底部左右邊界的圓角效果。 - 從設計工具獲取正確顏色代碼,修正顏色設置。 ## 顯示使用者資訊內容 - 在 `profileInfo` 顯示頭像、全名和電子郵件。 - 暫不顯示追蹤數與粉絲數。 ## 建立 `getUser` 方法 - 在身份驗證資料夾新增 `getUser` 方法,從 Firebase Firestore 查詢特定使用者資料。 - 使用 `DocumentSnapshot` 獲取資料。 ## 建立與處理 User Model - 在模型資料夾新增 `UserModel` 類別,包含全名、電子郵件與頭像 URL。 - 提供 `fromJson` 方法進行 JSON 轉換。 - 加入方法將 `UserModel` 轉為 `UserEntity`。 - 若 `photoURL` 為空,設置預設頭像 URL。 ## 錯誤處理與返回值 - 使用 `try-catch` 捕捉錯誤,返回錯誤訊息。 - 返回 `Either` 類型,右側包含 `UserEntity`,左側包含錯誤訊息。 ## 註冊 UseCase 並整合至 Profile 頁面 - 建立 `getUser` UseCase,註冊至依賴注入系統。 - 在 Profile 頁面呼叫 UseCase 獲取使用者資訊並更新顯示。 ## 建立 Profile Info 的狀態管理 - 在 `profile` 資料夾新增 `bloc` 資料夾,並建立 `profile_info_cubit.dart` 文件。 - 創建抽象類別,定義 `ProfileInfoLoading`、`ProfileInfoLoaded` 和 `ProfileInfoFailure` 三種狀態。 ## 實現 ProfileInfoCubit - 初始狀態設為 `ProfileInfoLoading`。 - 定義 `getUser` 方法,使用 `fold` 方法處理返回值。 - 左側返回 `ProfileInfoFailure`,右側返回 `ProfileInfoLoaded`,並傳遞 `UserEntity`。 ## 在 Profile 頁面注入 Cubit - 使用 `BlocProvider` 注入 `ProfileInfoCubit` 並調用 `getUser` 方法。 - 在 `Container` 中使用 `BlocBuilder` 監聽狀態變化。 ## 顯示使用者資訊 - 使用 `Container` 顯示頭像,設置圓形圖片並調整寬高。 - 顯示電子郵件與全名,並調整字體樣式。 ## 建立 Favorite Songs 的邏輯 - 在歌曲資料庫層新增 `getUserFavorites` 方法,從 `FirebaseFirestore` 查詢使用者收藏的歌曲 ID。 - 根據歌曲 ID 查詢 `songs` 集合,並轉換為 `SongEntity`。 - 捕捉錯誤並返回失敗訊息。 ## 註冊 Favorite Songs UseCase - 在 UseCase 資料夾新增 `GetUserFavoriteSongs`,封裝收藏歌曲的查詢邏輯。 - 在依賴注入系統中註冊 `GetUserFavoriteSongs` UseCase。 ## 整合 Favorite Songs 至 Profile 頁面 - 使用 `GetUserFavoriteSongs` 獲取使用者收藏歌曲列表。 - 在頁面下方顯示歌曲清單並設置適當的 UI 樣式。 ## 顯示使用者收藏的歌曲 - 在 `profile` 頁面創建 `Cubit` 管理顯示使用者收藏歌曲。 - 定義 `Loading`、`Loaded` 和 `Failure` 狀態。 - 在 `FavoriteSongsCubit` 中創建 `getFavoriteSongs` 方法,調用 `GetFavoriteSongs` UseCase 並處理結果。 ## 使用 Bloc 管理收藏歌曲狀態 - 使用 `BlocProvider` 注入 `FavoriteSongsCubit` 並調用 `getFavoriteSongs` 方法。 - 使用 `BlocBuilder` 監聽狀態變化,顯示進度條、歌曲列表或錯誤訊息。 ## 顯示歌曲資訊 - 使用 `Container` 顯示歌曲圖片,設置圖片大小與圓角。 - 顯示歌曲名稱、藝人名稱及歌曲長度,佈局與播放清單類似。 ## 添加和移除收藏歌曲 - 在 `FavoriteSongsCubit` 中創建 `removeSong` 方法移除收藏歌曲並更新狀態。 - 在 UI 中為每首歌曲添加按鈕,點擊後可移除該歌曲並更新 Firestore 資料。 - 使用 `Key` 避免更改其他歌曲的狀態。 ## 音樂播放頁面導向 - 在歌曲項目上設置點擊事件,點擊後使用 `Navigator.push` 跳轉到歌曲播放頁面並傳遞歌曲資料。 ## 完成專案 - 完成 Spotify 克隆專案,檢查所有功能是否運作正常。 # Terminology - **Clean Architecture**: 一種將應用程序分為三層(Domain、Data、Presentation)的架構模式,強調分離關注點以提升維護性和擴展性。 - **State Management**: 管理應用程序中狀態變更的方法,以確保資料一致性與視圖同步。 - **BLoC (Business Logic Component)**: 將業務邏輯與 UI 分離,利用資料流來處理事件和狀態更新。 - **Cubit**: BLoC 中一種簡化形式,專注於狀態管理而不處理事件流。 - **Dependency Inversion Principle (DIP)**: 依賴倒置原則,強調高層模組不應依賴低層模組,而應共同依賴抽象。 - **Service Locator Pattern**: 一種設計模式,用於動態解析和提供依賴,簡化物件的管理和取得。 - **GetIt**: Flutter 中的依賴注入框架,用於管理和獲取實例,減少代碼耦合。 - **Dartz**: Dart 的函式式程式庫,用於處理錯誤和函式式數據類型如 `Option` 和 `Either`。 - **Firestore**: Google 的 NoSQL 雲端數據庫,適用於即時資料存取和同步。 - **Firebase Authentication**: Firebase 提供的身份驗證服務,用於實現用戶的身份管理與驗證。 - **Just Audio**: 一個用於播放音頻的 Dart 套件,支援本地和遠端音頻資源。 - **Figma**: UI/UX 設計工具,主要用於設計和分享應用界面和網站。 - **Light Theme**: 使用淺色背景和深色文字的界面主題,用於增強視覺辨識。 - **Dark Theme**: 使用深色背景和淺色文字的界面主題,減少夜間模式下的眼睛疲勞。 - **Presentation Layer**: Clean Architecture 中的一層,負責 UI 和用戶交互。 - **Domain Layer**: Clean Architecture 中的一層,處理業務邏輯和應用核心邏輯。 - **Data Layer**: Clean Architecture 中的一層,管理數據來源和數據存取。 - **ThemeData**: 用於定義 Flutter 應用的主題屬性,如顏色、文字樣式等。 - **Assets Folder**: 專案資源文件夾,包含圖片、字型等資產。 - **SVG (Scalable Vector Graphics)**: 一種基於 XML 的圖形格式,可伸縮和高度精確顯示圖形。 - **Stateless Widget**: 不帶狀態的組件,無法在生命周期中改變其屬性或數據。 - **Stateful Widget**: 帶狀態的組件,允許在生命周期中更新其數據和界面。 - **initState**: 用於初始化狀態的函數,在Stateful Widget創建時執行一次。 - **Future**: 表示可能在未來完成的異步操作的對象。 - **Navigator**: 用於管理應用程式頁面堆疊的工具,實現頁面導航。 - **pushReplacement**: 替換當前頁面並導航到新頁面的Navigator方法。 - **MaterialPageRoute**: 提供基於Material Design的頁面導航路由。 - **Scaffold**: 提供Material Design基本佈局結構的組件。 - **Stack**: 容器組件,用於將子組件按順序堆疊。 - **BoxDecoration**: 用於設置容器的背景、邊框或陰影等裝飾。 - **DecorationImage**: 用於在BoxDecoration中設置背景圖片。 - **Spacer**: 自適應佔位符,用於調整子組件之間的間距。 - **SizedBox**: 設置固定尺寸或空間的組件。 - **Align**: 用於控制子組件在父容器中的對齊方式。 - **TextStyle**: 定義文字樣式的類,如字體大小、顏色和字體粗細。 - **Padding**: 用於設置容器內部內容的邊距。 - **ElevatedButton**: 提供凸起效果的Material Design按鈕組件。 - **styleFrom**: 用於自定義ElevatedButton樣式的輔助方法。 - **Opacity**: 設置組件透明度的屬性或組件。 - **Const Constructor**: 用於創建不可變對象的構造方法,優化效能。 - **Scaffold**:Flutter 中用於構建基礎頁面結構的 widget,提供應用欄、浮動按鈕等基本 UI 元素。 - **Navigator.push**:用於導航至新頁面的 Flutter 方法,將當前頁面推到堆疊的頂部。 - **MaterialPageRoute**:用於定義頁面路由的類別,提供頁面過渡動畫和構造函數。 - **Stack**:Flutter 中的佈局 widget,允許子 widget 層疊顯示。 - **SizedBox**:用於設置固定尺寸或間距的空間 widget。 - **BoxDecoration**:用於定義容器的外觀,例如背景顏色、邊框或陰影的屬性類別。 - **BackdropFilter**:用於對 widget 背景進行模糊處理或其他濾鏡效果的 widget。 - **ClipRRect**:用於對 widget 進行圓角裁剪的 widget。 - **SVG Picture.asset**:用於在 Flutter 中顯示 SVG 圖像的工具,支持矢量圖形渲染。 - **BoxShape.circle**:用於設置 BoxDecoration 的形狀為圓形的屬性。 - **HydratedCubit**:Flutter Bloc 提供的一個擴展類,支持狀態的持久化存儲。 - **ThemeMode**:用於定義應用主題模式的枚舉,包含 light、dark 和 system 模式。 - **MultiblocProvider**:用於注入多個 Cubit 或 Bloc 以供整個應用程序使用的工具。 - **BlocBuilder**:Flutter Bloc 提供的 widget,用於根據狀態變化構建 UI。 - **GestureDetector**:用於檢測點擊、滑動等用戶手勢的 widget。 - **Context.read**:Flutter Bloc 中提供的方法,用於讀取 Bloc 或 Cubit 的實例。 - **emit**:在 Cubit 中用於觸發新狀態更新的方法。 - **PathProvider**:用於獲取文件系統路徑(如應用文檔目錄)的 Flutter 插件。 - **FontWeight.medium**:用於設置文字字重的屬性,表示中等粗細。 - **Hex Color**:用於定義顏色的十六進制格式,例如 `#FFFFFF` 表示白色。 - **FL Block**: 用於管理 Flutter 中狀態的套件,將業務邏輯與 UI 分離,提供更清晰的狀態管理架構。 - **Hydrated Block**: 一種能夠自動將狀態持久化的 FL Block 擴展,方便在應用重啟後恢復狀態。 - **Path Provider**: 用來獲取設備上的目錄路徑,常用於持久化數據存儲。 - **Cubit**: 一種輕量級的狀態管理方式,FL Block 中的基本單位,用來管理單一的狀態。 - **Hydrate Cubit**: 是 Cubit 的一個擴展,提供自動狀態持久化功能,可以保存並恢復先前的狀態。 - **MaterialApp**: Flutter 中用來設置整個應用的主結構和樣式的 widget。 - **MultiBlocProvider**: 用來在 Flutter 應用中提供多個 Bloc 的方法,通常包裹 MaterialApp 來提供 Bloc 設定。 - **BlocBuilder**: 用於構建界面的 Flutter 小部件,根據 Bloc 的狀態變更來刷新 UI。 - **State**: 在 Bloc 中,表示應用或元件的狀態數據,可以是任何類型的資料。 - **Emit**: 在 Bloc 中,表示發送新的狀態以通知界面更新。 - **ThemeMode**: 控制應用界面顯示模式(如黑暗模式或光明模式)的類型。 - **Dark Theme**: 用於顯示深色背景和亮色文字的應用主題。 - **Light Theme**: 用於顯示亮色背景和深色文字的應用主題。 - **GestureDetector**: 用來檢測用戶觸摸手勢(如點擊)的 widget。 - **Context.read**: 在 Bloc 中,用來讀取當前上下文中注入的 Bloc 實例的方法。 - **Constructor**: 用來創建類實例的函數,通常在類的初始化過程中傳遞必要參數。 - **Initial State**: 在 Bloc 或 Cubit 中定義的初始狀態,應用啟動時的默認狀態。 - **Update Theme**: 更改應用主題模式的函數,根據用戶選擇切換光明或黑暗模式。 - **Block Provider**: 提供 Bloc 實例的上下文,讓 Bloc 可以在整個應用中被使用。 - **BlockListener**: 用於監聽 Bloc 狀態改變並做出響應的 widget。 - **Figma**: 一個設計工具,常用於 UI/UX 設計,協助設計師創建界面原型。 - **SVG**: 矢量圖形格式,常用於網頁和應用中顯示高品質圖像,無論放大縮小均不失真。 - **PNG**: 位圖圖像格式,支持透明背景,廣泛應用於網頁和應用程序中。 - **Stateless Widget**: Flutter 中一種無狀態的組件,不會根據用戶交互改變自身狀態,適用於靜態顯示的 UI 元素。 - **Scaffold**: Flutter 中用來構建界面結構的 widget,通常包括 AppBar、Drawer、Body 等部分。 - **Stack**: 用來將多個 widget 層疊顯示的容器,通常與 alignment 配合使用來設置每個 widget 的位置。 - **Alignment**: 設定 widget 在父容器中的位置,通常用於 Stack 或其他容器類型。 - **Column**: 用來將多個子 widget 垂直排列的容器。 - **SizedBox**: 用於設置子 widget 之間的固定空間,常用於調整間距。 - **TextButton**: Flutter 中的一種扁平化按鈕樣式,通常用於輕量級操作。 - **Expanded**: 用來讓子 widget 擴展至父容器的剩餘空間,通常與 Flex 類型的容器(如 Row、Column)配合使用。 - **Padding**: 設置子 widget 與其父容器邊緣之間的空白區域。 - **TextStyle**: 用於定義文本顯示樣式的類型,包含字體、顏色、大小等屬性。 - **Brightness**: 用來指示顯示模式(如暗色模式或亮色模式)的屬性。 - **AppBar**: 頁面頂部的標題欄,通常包括頁面標題和其他操作按鈕。 - **Navigator**: 用來管理頁面導航的 Flutter 類,負責頁面之間的切換和路徑管理。 - **IconButton**: Flutter 中的一種包含圖標的可點擊按鈕,通常用於操作按鈕。 - **Opacity**: 控制 widget 透明度的屬性,用於設置元素的可見度。 - **Theme**: 用來定義應用中全局樣式的設置,包括顏色、字體和顯示模式等。 - **Extension**: Dart 語言中的擴展,用於為現有類型添加方法或屬性,以提高代碼的可重用性。 - **Scaffold**:Flutter 的一個基本結構元件,用於構建應用的頁面框架,包含 AppBar、Body 等常見佈局。 - **Column**:Flutter 的佈局元件,將子元件以垂直方向排列。 - **Padding**:用於為元件設置內部間距,常用於控制子元件與邊界的距離。 - **InputDecoration**:定義 TextField 的外觀,包括邊框、提示文字等屬性。 - **ThemeData**:用於定義應用的主題樣式,例如顏色、字體、按鈕樣式等。 - **Navigator**:用於在頁面間導航的工具,可推送或彈出頁面路由。 - **MaterialPageRoute**:Flutter 中的一種路由類型,支援 Material Design 樣式的頁面過渡動畫。 - **TextStyle**:用於設置文本的樣式,例如字體大小、顏色和粗細。 - **AppBar**:應用程式的頂部欄,用於顯示標題、按鈕或導航圖標。 - **MainAxisAlignment**:用於控制 Row 或 Column 中子元件的主軸對齊方式。 - **CrossAxisAlignment**:控制 Row 或 Column 中子元件的交叉軸對齊方式。 - **TextField**:用於接受用戶輸入的元件,可設置提示文字、密碼模式等屬性。 - **OutlinedInputBorder**:定義 TextField 的外框樣式,通常用於自訂邊框。 - **GestureDetector**:用於處理手勢事件,例如點擊、拖動和雙擊。 - **StatefulWidget**:Flutter 中的有狀態元件,支援動態更新界面。 - **StatelessWidget**:Flutter 中的無狀態元件,界面是靜態的,不會隨狀態變化。 - **Expanded**:Flutter 的佈局元件,用於在 Row 或 Column 中分配剩餘的空間。 - **Opacity**:用於設置元件的透明度,以控制其顯示效果。 - **SVG Picture**:Flutter 的套件,用於顯示 SVG 格式的矢量圖形。 - **SizedBox**:用於創建具有固定寬高或用於在元件間創建間距的空間元件。 - **Firebase CLI**:Firebase 提供的命令列工具,用於初始化和管理 Firebase 專案及其配置。 - **Standalone Binary**:獨立執行檔形式的 Firebase CLI,無需其他工具即可執行。 - **Pubspec.yaml**:Dart/Flutter 專案的配置檔案,用於管理依賴和專案元數據。 - **InitializeApp**:Firebase 初始化函數,用於在應用啟動時設置 Firebase 配置。 - **Clean Architecture**:軟體開發架構,將系統分為多層(例如 Domain、Data、Presentation),強調分層隔離與依賴方向。 - **Domain Layer**:負責定義業務邏輯和核心實體,與框架和技術無關。 - **Entity**:代表核心業務邏輯中的資料結構,如用戶實體(User Entity)。 - **Repository**:一種抽象層,用於隔離業務邏輯與數據來源的實現。 - **Future**:Dart 中表示異步操作結果的類型,用於處理非同步方法。 - **Firebase Authentication**:Firebase 提供的身份驗證服務,用於用戶註冊和登錄。 - **Create User With Email And Password**:Firebase Authentication 提供的 API,用於通過電子郵件和密碼創建新用戶。 - **Try-Catch**:Dart 中的異常處理機制,用於捕獲和處理執行過程中的錯誤。 - **Dependency Inversion Principle (DIP)**:設計原則,強調高層模組不應依賴低層模組,而是依賴抽象。 - **Get It**:Flutter/Dart 的依賴注入工具,用於管理依賴的實例化和生命周期。 - **Service Locator**:一種依賴管理模式,通過集中註冊和查詢來管理對象實例。 - **Register Singleton**:在 Get It 中註冊單例類型的方式,確保應用中只創建一個實例。 - **Abstract Class**:一種僅定義方法和屬性的介面,具體邏輯需由其子類實現。 - **Json Serialization**:將物件轉換為 JSON 格式,或將 JSON 格式轉換為物件的過程。 - **Create User Request**:一種數據模型,封裝用戶註冊所需的資料,例如電子郵件、密碼和全名。 - **SL (Service Locator)**:用於標識和訪問依賴的全局實例變數,在整個專案中共享。 - **抽象類別**:用於定義基礎行為的類別,無法直接實例化,需由子類實現具體方法。 - **泛型參數**:允許類別或方法在聲明時指定具體的資料類型,提供靈活性與類型安全性。 - **呼叫方法**:類別中的特殊函式,實現具體邏輯,供其他代碼調用。 - **回傳類型**:方法的輸出類型,定義該方法預期返回的資料型態。 - **右側**:`Either`資料結構中表示成功的結果。 - **左側**:`Either`資料結構中表示失敗的結果。 - **服務定位器**:一種設計模式,用於集中管理依賴項並簡化依賴注入。 - **資料層**:應用程式的底層結構,負責數據的存取與操作。 - **域層**:處理業務邏輯的層級,位於資料層與表現層之間。 - **表現層**:應用程式的用戶界面,直接與使用者互動。 - **Firebase 認證**:Google 提供的身份驗證服務,支援多種登入方式。 - **狀態管理**:應用程式中處理資料與狀態變化的機制。 - **Navigator**:Flutter 提供的路由工具,用於管理頁面導航與歷史記錄。 - **MaterialPageRoute**:Flutter 中的一種路由,用於管理頁面過渡效果。 - **Scaffold**:Flutter 中的基礎佈局工具,提供標準化的界面結構。 - **Snackbar**:用於短暫顯示訊息的彈出式元件,通常用於通知或提示。 - **異常處理**:程序運行中對錯誤情況的捕獲與處理機制。 - **控制器**:Flutter 中的物件,用於監視與控制輸入框的內容。 - **try-catch**:用於捕獲程式執行期間可能出現的異常,並進行處理。 - **removeUntil**:Navigator 方法,用於清空路由堆疊並導航到指定頁面。 - **抽象類別 (Abstract Class)**:定義方法結構但不實作的類別,必須由子類別實作具體功能。 - **泛型 (Generics)**:提供類別或方法參數化的能力,以提升程式碼的靈活性與重用性。 - **服務定位器 (Service Locator)**:一種設計模式,集中管理與提供依賴項的實例。 - **依賴注入 (Dependency Injection)**:將物件的依賴從外部注入,提升模組化與可測試性。 - **Firebase 認證 (Firebase Authentication)**:提供多種方式進行用戶驗證的服務,例如電子郵件、密碼、Google 登入等。 - **Firebase 存儲 (Firebase Storage)**:用於存儲文件、圖片、音樂等檔案的雲存儲服務。 - **Firestore 資料庫 (Cloud Firestore)**:雲端 NoSQL 資料庫,支持即時同步與查詢。 - **文件集合 (Collection)**:Firestore 中用於分組和管理文件的結構,類似於資料庫的表。 - **文件 (Document)**:Firestore 中的基本資料單元,包含鍵值對結構的資料。 - **自動生成 ID (Auto ID)**:Firestore 提供的功能,為文件生成唯一標識符。 - **異常處理 (Exception Handling)**:處理程式運行中可能出現的錯誤或異常情況的機制。 - **回傳類型 (Return Type)**:方法或函式返回的值的資料型別。 - **JSON 格式 (JSON Format)**:用於資料交換的輕量級格式,結構為鍵值對。 - **單一子滾動視圖 (SingleChildScrollView)**:Flutter 中用於在空間不足時滾動顯示內容的 widget。 - **頁面導航 (Page Navigation)**:應用中切換頁面的過程,常使用 Navigator 來實現。 - **SnackBar**:Flutter 提供的一種 UI 元件,用於在畫面下方短暫顯示提示訊息。 - **右值 (Right)**:Either 類中的成功結果,用於表示操作成功的輸出。 - **左值 (Left)**:Either 類中的錯誤結果,用於表示操作失敗的原因或訊息。 - **請求認證 (Request Authentication)**:檢查用戶是否通過身份驗證的過程,確保數據操作的安全性。 - **規則編輯 (Rules Editing)**:設置 Firestore 或 Storage 的讀寫權限的操作,確保資料的安全性和可用性。 - 專案文件夾:存放專案相關資源和程式碼的結構化目錄。 - 資產目錄:專門存放圖片、向量、字型等應用所需的靜態資源的文件夾。 - 向量圖:通常為 SVG 格式的圖片,具有可縮放性且不會失真。 - PNG 格式:一種無損壓縮的點陣圖格式,適用於圖片資產。 - 頂層卡片:首頁中的主要設計元素,用於展示關鍵內容或圖片的元件。 - AppBar:應用程式頂部的導航欄,用於顯示標題、按鈕等內容。 - 頂層導覽頁:應用的主要頁面,例如首頁、使用者頁面等。 - Stateless Widget:無狀態元件,適用於靜態不變的 UI 元素。 - Stateful Widget:有狀態元件,適用於需要更新或互動的 UI 元素。 - 單一滾動視圖:允許單方向滾動的視圖元件。 - 堆疊:一種容器元件,允許子元件重疊排列。 - 靜態常數:用於存放不變的值,例如資源路徑或顏色代碼的變數。 - 頂部卡片:用於首頁的主視覺元件,顯示背景圖片或相關資訊。 - 對齊屬性:設定元件的相對位置,例如左對齊、居中或底部對齊。 - Padding:設定元件內部的邊距,用於調整元件的顯示間距。 - 標籤顏色:設定標籤文字在不同模式下的顏色,例如深色模式或亮色模式。 - 頂部控制器:用於管理 TabBar 或類似元件的控制器。 - 單一狀態混合:讓元件支援單一狀態的生命週期混合模式。 - 主色:應用程式中主要使用的顏色,用於保持一致的視覺風格。 - 字型大小:設定文字的顯示大小,以適應不同的設計需求。 - 乾淨架構:一種分層架構設計,將應用分為資料層、領域層和展示層。 - 實體:領域層中用於描述核心業務邏輯和資料的物件。 - 模型:資料層中用於表示與資料來源交互的資料結構。 - JSON:一種輕量級的資料交換格式,用於在前後端間傳遞資料。 - Firestore:Google 提供的雲端 NoSQL 資料庫服務,適合實時同步應用。 - 時間戳:用於記錄特定時間的標準格式資料類型。 - 抽象類別:未實現具體方法的類別,用於定義通用的介面或契約。 - 資料夾結構:將專案中不同責任的檔案組織到相關的資料夾中。 - 依賴反轉原則:設計模式,確保高階模組不依賴低階模組,兩者皆依賴於抽象。 - Either:一種用於封裝結果和錯誤的資料結構,可用於錯誤處理。 - 查詢快照:Firestore 中查詢的結果物件,包含資料集合的多個文件。 - 映射方法:將 JSON 資料轉換為 Dart 物件的過程,例如 fromJson 方法。 - 擴展方法:為現有類別添加功能的方法,通常用於轉換資料類型。 - 使用案例:描述特定業務操作邏輯的類別,負責調用領域層的服務。 - 服務定位器:一種依賴注入模式,用於管理和提供應用所需的實例。 - 異步操作:非同步執行的程式邏輯,例如讀取遠端資料庫。 - Try-Catch:用於捕捉和處理程式執行期間可能出現的異常的結構。 - 權重:在 Firebase 中使用 orderBy 進行排序時,用於指定排序的欄位。 - 限制:查詢時指定返回結果的數量,例如限制為最近三筆資料。 - 錯誤訊息:當操作失敗時向使用者回報的錯誤描述,提升使用體驗。 - 狀態管理(State Management):用於管理應用中狀態和其變化的技術,例如 Bloc。 - Bloc(Business Logic Component):Dart 中的一個模式,分離業務邏輯與 UI 代碼。 - Cubit:Bloc 的簡化版本,僅負責處理狀態和其變更。 - BlocBuilder:Bloc 狀態的監聽器,用於在狀態變化時重新構建 UI。 - 狀態(State):應用中當前的資料和 UI 狀態,例如 Loading、Loaded 和 Failure。 - ListView:Flutter 中用於顯示可滾動列表的組件。 - 橫向滾動(Horizontal Scroll):ListView 的一種滾動方向設置,適合顯示橫向資料。 - BlocProvider:Bloc 的提供器,用於將 Bloc 注入到小部件樹中。 - TapBarView:一種在 Flutter 中實現頁籤切換內容的組件。 - 圖片裝飾(BoxDecoration):用於設置小部件背景或邊框的裝飾。 - 網路圖片(NetworkImage):從 URL 加載的圖片,通常用於展示遠端資源。 - Expanded:Flutter 中的佈局組件,用於擴展子組件以填充剩餘空間。 - 圓角邊框(BorderRadius.circular):設置小部件邊框的圓角半徑。 - 大小框(SizedBox):Flutter 中用於設置固定大小的空間或間距。 - 語義分離(SeparatedBuilder):ListView 的生成方法,用於分隔子項目。 - 圖標(Icon):用於顯示小的圖片或圖形符號,例如播放按鈕圖標。 - 主題檢查(isDarkMode):檢查當前應用主題模式是否為深色模式。 - Transformation(Matrix4):用於移動、縮放或旋轉小部件的屬性。 - 子部件對齊(Alignment):設置小部件內的內容位置,例如底部右對齊(BottomRight)。 - 狀態管理(State Management):用於管理應用中狀態和其變化的技術,例如 Bloc。 - Bloc(Business Logic Component):Dart 中的一個模式,分離業務邏輯與 UI 代碼。 - Cubit:Bloc 的簡化版本,僅負責處理狀態和其變更。 - BlocBuilder:Bloc 狀態的監聽器,用於在狀態變化時重新構建 UI。 - 狀態(State):應用中當前的資料和 UI 狀態,例如 Loading、Loaded 和 Failure。 - ListView:Flutter 中用於顯示可滾動列表的組件。 - 橫向滾動(Horizontal Scroll):ListView 的一種滾動方向設置,適合顯示橫向資料。 - BlocProvider:Bloc 的提供器,用於將 Bloc 注入到小部件樹中。 - TapBarView:一種在 Flutter 中實現頁籤切換內容的組件。 - 圖片裝飾(BoxDecoration):用於設置小部件背景或邊框的裝飾。 - 網路圖片(NetworkImage):從 URL 加載的圖片,通常用於展示遠端資源。 - Expanded:Flutter 中的佈局組件,用於擴展子組件以填充剩餘空間。 - 圓角邊框(BorderRadius.circular):設置小部件邊框的圓角半徑。 - 大小框(SizedBox):Flutter 中用於設置固定大小的空間或間距。 - 語義分離(SeparatedBuilder):ListView 的生成方法,用於分隔子項目。 - 圖標(Icon):用於顯示小的圖片或圖形符號,例如播放按鈕圖標。 - 主題檢查(isDarkMode):檢查當前應用主題模式是否為深色模式。 - Transformation(Matrix4):用於移動、縮放或旋轉小部件的屬性。 - 子部件對齊(Alignment):設置小部件內的內容位置,例如底部右對齊(BottomRight)。 - **Stateless Widget**:Flutter 中一種無狀態的 widget,內容固定,不會因用戶操作而改變。 - **Scaffold**:Flutter 提供的基本頁面結構,包含 AppBar、Body、FloatingActionButton 等常見元素。 - **GestureDetector**:一個偵測用戶手勢(如點擊、滑動)的 widget,用於添加互動功能。 - **Navigator**:用於管理頁面導航的 Flutter 組件,提供 push 和 pop 方法實現頁面跳轉。 - **MaterialPageRoute**:一種路由類型,提供 Material Design 樣式的頁面轉場效果。 - **AppBar**:Scaffold 中的標準應用欄,用於顯示標題和操作按鈕。 - **IconButton**:一個包含圖標且支持點擊事件的按鈕 widget。 - **NetworkImage**:用於從網絡加載圖片的類,適合動態顯示遠端圖片資源。 - **SingleChildScrollView**:一種支持滾動的 widget,適用於子內容可能超出屏幕的情況。 - **Column**:一種將子 widget 垂直排列的布局組件。 - **Padding**:用於設置 widget 周圍內邊距的 widget。 - **BorderRadius**:用於設置邊框的圓角屬性,通常搭配 BoxDecoration 使用。 - **BoxDecoration**:用於裝飾 container,例如設置背景色、圖片或圓角等樣式的類。 - **TextStyle**:用於設置文字樣式的類,包括字體大小、顏色、粗細等屬性。 - **MainAxisAlignment**:控制主軸(如 Column 的垂直軸)上子 widget 的排列方式的屬性。 - **OutlineButton**:Flutter 中一種邊框按鈕樣式,適用於低優先級操作(現已棄用,建議用 OutlinedButton)。 - **Icon**:用於顯示 Material Design 圖標的 widget。 - **setState**:Flutter 中的一個方法,用於觸發狀態改變並重新構建 UI(僅限 Stateful Widget 使用)。 - **Container**:一種多功能的 widget,用於設置大小、邊距、背景等樣式的容器。 - **ActionBar**:通常指 AppBar 的右側操作區域,可用於放置按鈕或功能圖標。 - **Slider**:一個允許用戶調整值(例如進度條)的 widget,適合用於音樂播放進度控制。 - **Cubit**:Flutter 中輕量級的狀態管理工具,基於 Bloc 提供簡化的狀態處理方式。 - **Stream**:Dart 中的數據流,用於監聽事件並響應,例如音樂的播放進度更新。 - **AudioPlayer**:Just Audio 套件中的類,用於處理音頻播放、暫停、停止等功能。 - **Duration**:Dart 標準庫中的類,表示時間間隔,用於處理音樂的時長與進度。 - **listen**:Stream 中的一個方法,用於訂閱事件並執行回調函數以更新 UI 或數據。 - **BlockProvider**:Flutter Bloc 提供的一個 widget,用於將 Cubit 或 Bloc 注入到 widget 樹中。 - **BlockBuilder**:一個基於狀態變化來構建 UI 的 Bloc 工具,適合響應式設計。 - **CircularProgressIndicator**:Flutter 中的圓形進度指示器,用於顯示加載狀態。 - **min/max**:Slider 的屬性,用於設置最小值和最大值,控制滑塊的範圍。 - **setShape**:BoxDecoration 的屬性,用於設置形狀,例如圓形或矩形。 - **BoxShape.circle**:Flutter 提供的形狀類型,表示圓形,適用於按鈕設計。 - **GestureDetector**:用於檢測觸摸手勢的 widget,例如點擊、滑動等。 - **play/pause**:音頻播放的常見功能,控制音樂的開始與暫停。 - **format**:將數據轉換為特定顯示格式的操作,例如將時間轉換為「分鐘:秒」。 - **AppColors.primary**:一個應用主題顏色的變量,通常用於統一設計風格。 - **emit**:Cubit 的方法,用於向 UI 傳遞新的狀態更新。 - **try/catch**:Dart 中的錯誤處理機制,用於捕獲和處理異常情況。 - **dispose**:用於釋放資源或清理數據的方法,避免內存洩漏。 - **Context.read**:Bloc 提供的方法,用於訪問注入的 Cubit 或 Bloc 並獲取其數據。 - **Firebase Authentication**:提供用戶身份驗證功能,支持多種登入方式如郵件、Google、Facebook 等。 - **Firestore**:Firebase 的雲端 NoSQL 資料庫,用於存儲結構化數據,支持實時同步功能。 - **Collection**:Firestore 中的一組文件集合,類似資料表的概念。 - **Document**:Firestore 中的資料單元,存儲具體的鍵值對,類似資料表中的一列資料。 - **Subcollection**:Firestore 文件中的嵌套集合,用於組織更複雜的數據結構。 - **Doc Method**:Firestore 的方法,用於創建或操作具有特定 ID 的文件。 - **Set Method**:Firestore 中的 API,用於以指定 ID 創建或覆寫文件。 - **Add Method**:Firestore 中的 API,用於新增文件並自動生成文件 ID。 - **Query Snapshot**:Firestore 查詢的結果集合,包含一組文件的快照。 - **Where Clause**:Firestore 的查詢條件,用於篩選符合特定條件的文件。 - **Try-Catch Block**:程式語言中的結構,用於捕捉和處理可能發生的異常錯誤。 - **Boolean**:布林型別,表示邏輯值(真或假)。 - **Cubit**:Flutter Bloc 架構的一部分,用於管理應用的狀態。 - **Service Locator**:設計模式,用於集中管理服務實例的創建和訪問。 - **Use Case**:應用程式中的業務邏輯單位,封裝特定功能的實現。 - **Entity**:數據模型的定義,用於描述業務邏輯中的核心數據結構。 - **Model**:與資料存儲交互的資料結構,通常映射到資料庫中的數據格式。 - **Favorite Button**:UI 元件,用於標記歌曲是否被加入收藏。 - **Stateless Widget**:Flutter 中不需要管理狀態的 UI 組件類型。 - **Bloc Builder**:Flutter Bloc 的組件,用於監聽和重建基於 Cubit 或 Bloc 的狀態變化。 - **Stateless Widget**:一種無狀態的 Flutter 小部件,用於構建不依賴可變數據的介面。 - **AppBar**:Flutter 提供的標題欄組件,通常用於顯示標題、操作按鈕等。 - **Navigator**:Flutter 的路由管理工具,用於頁面導航和路由操作。 - **IconButton**:一個帶有圖示的按鈕,用於執行特定的操作。 - **Column**:Flutter 的佈局小部件,用於將子項垂直排列。 - **Container**:Flutter 的基礎組件,可用於佈局、裝飾和尺寸調整。 - **BoxDecoration**:用於裝飾容器的類,可設置背景色、圓角等樣式。 - **Figma**:一款用於設計和原型製作的協作工具。 - **Firebase Authentication**:提供用戶身份驗證功能的 Firebase 服務。 - **Firestore**:Firebase 提供的雲端 NoSQL 資料庫服務。 - **DocumentSnapshot**:從 Firestore 中讀取的單筆文件數據的快照。 - **Entity**:程式中的核心業務邏輯對象,通常用於封裝數據。 - **Model**:程式中用於處理數據的物件,包含與資料來源交互的邏輯。 - **toJson**:將物件轉換為 JSON 格式的函式,便於傳輸和存儲。 - **fromJson**:從 JSON 格式數據建立物件的函式,便於數據解析。 - **URL**:統一資源定位符,用於指定網絡資源的位置。 - **Either**:一種函數式程式設計中表示可能成功或失敗的數據結構。 - **Future**:Dart 的異步操作類型,用於處理非同步任務。 - **Try-Catch**:用於捕獲和處理程式異常的結構化方式。 - **Default Image**:用於替代缺失圖像的一種預設圖像資源。 - **Use Case**:軟體設計中的業務邏輯單元,用於執行特定操作或用例。 - **BLoC (Business Logic Component)**:Flutter 中的狀態管理工具,將業務邏輯與 UI 分離。 - **Cubit**:BLoC 的簡化版本,用於管理單一狀態流的邏輯。 - **State Management**:應用程式中用於跟蹤 UI 狀態的技術,確保資料和介面一致性。 - **Abstract Class**:一種無法直接實例化的類,通常用於定義行為介面。 - **Profile Info Loading**:用於表示用戶資訊正在加載的狀態。 - **Profile Info Loaded**:用於表示用戶資訊已成功加載的狀態,並攜帶用戶實體數據。 - **Profile Info Failure**:用於表示用戶資訊加載失敗的狀態,通常包含錯誤訊息。 - **Use Case**:代表應用特定功能的邏輯單元,實現業務規則。 - **Either**:一種數據結構,用於表示成功(右側)或失敗(左側)的結果。 - **Fold Method**:操作 Either 結構,分別處理成功與失敗的邏輯分支。 - **BLoC Provider**:用於將 BLoC 實例注入到子樹的 Flutter 組件。 - **BLoC Builder**:用於在狀態更改時重新構建 UI 的 Flutter 組件。 - **CircularProgressIndicator**:一個 Flutter 組件,用於顯示正在進行的操作。 - **BoxDecoration**:定義容器的裝飾,包括顏色、圖片和形狀等。 - **NetworkImage**:Flutter 中用於從網路加載圖像的工具類。 - **Firestore Collection**:Firebase Firestore 的資料結構,用於存儲和組織文檔。 - **fromJson Method**:將 JSON 數據轉換為物件實例的函式。 - **Repository Pattern**:一種設計模式,用於抽象化數據訪問層。 - **Service Locator**:一種用於管理和提供服務或依賴項的設計模式。 - **Song Model**:代表歌曲數據的物件模型,包含相關屬性和方法。 - **Song Entity**:表示業務層級的歌曲對象,通常用於介面或業務邏輯中。 - **Bloc (Business Logic Component)**:一種在 Flutter 中管理應用程式狀態的架構,將商業邏輯與 UI 分離。 - **Cubit**:一種簡化的 Bloc,適用於簡單的狀態管理,通常用於單一狀態的管理。 - **State Management**:一種處理應用程式狀態的技術,保證 UI 與資料的一致性。 - **Abstract Class**:定義方法但不實作的類別,用於規範子類別的行為。 - **Favorite Songs Loading**:用來表示用戶的最愛歌曲正在加載的狀態。 - **Favorite Songs Loaded**:用來表示最愛歌曲已加載的狀態,並攜帶歌曲數據。 - **Favorite Songs Failure**:用來表示最愛歌曲加載失敗的狀態,通常會顯示錯誤訊息。 - **Use Case**:應用中的具體功能單位,處理業務邏輯並返回結果。 - **Bloc Provider**:一個將 Bloc 實例提供給子樹的 Widget,使得 Bloc 可以在 Widget 樹中共享。 - **Bloc Builder**:監聽 Bloc 狀態改變並更新 UI 的 Widget。 - **CircularProgressIndicator**:顯示正在處理的圓形進度條。 - **Padding**:用於增加內邊距,讓 Widget 不會緊貼其父容器的邊界。 - **NetworkImage**:從網路加載圖像的 Flutter Widget,常用於顯示遠端圖片。 - **BoxDecoration**:為容器提供裝飾,包括顏色、邊框、陰影等樣式。 - **Navigator Push**:用於在 Flutter 中執行頁面跳轉。 - **Key**:用於在 Widget 樹中識別 Widget 的唯一標識符,有助於提高性能並避免重建不必要的部分。 - **MaterialPageRoute**:Flutter 中的一種頁面路由,用於簡單的頁面轉換。 - **ListView**:顯示可滾動的項目列表,常用於顯示長列表數據。 - **SizedBox**:用於設置固定大小的空間,可以用來調整 UI 的間距。 - **GestureDetector**:用於檢測用戶手勢(如點擊、拖動等)的 Widget,通常與事件處理相關聯。 - **FireStore**:Firebase 提供的 NoSQL 資料庫服務,用於存儲和同步數據。

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully