Skip to content

Refactor rename package #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7bf3fe3
chore(deps): update dependencies and migrate to Flutter News App
fulleni Jul 23, 2025
8bd68d8
ci: update CI/CD configurations
fulleni Jul 23, 2025
ed5ed16
build(android): update app configuration and naming
fulleni Jul 23, 2025
33d1130
refactor(dependencies): remove "ht_" prefix from package imports
fulleni Jul 23, 2025
4f4eae9
refactor(account): update imports and package names
fulleni Jul 23, 2025
4a7651f
refactor(account): update imports and rename exception types
fulleni Jul 23, 2025
b6dda33
refactor(dependencies): rename and restructure package imports
fulleni Jul 23, 2025
1072d33
refactor(authentication): update imports and exceptions
fulleni Jul 23, 2025
45398df
refactor(data_repository): replace HtDataRepository with DataRepository
fulleni Jul 23, 2025
137f36d
refactor(headlines-feed): update imports and rename classes
fulleni Jul 23, 2025
0333816
refactor(headlines-search): update imports and errors
fulleni Jul 23, 2025
79f2c88
refactor(settings): update imports and organize dependencies
fulleni Jul 23, 2025
65698b4
refactor(shared): update imports and package references
fulleni Jul 23, 2025
f10042f
refactor(router): update imports and package names
fulleni Jul 23, 2025
803bbb5
fix(l10n): update import path for AppLocalizations
fulleni Jul 23, 2025
f5a77b9
docs(README): update project metadata and licensing information
fulleni Jul 23, 2025
d7062c2
docs(README): update content and clarify getting started instructions
fulleni Jul 23, 2025
8458a9f
feat(README): update headlines feed description
fulleni Jul 23, 2025
a6afbc0
refactor(headline-details): improve chip creation in _HeadlineDetails…
fulleni Jul 23, 2025
7fc8839
style(headlines-search): update TODO comments and improve code consis…
fulleni Jul 23, 2025
dbb02ff
refactor(dependencies): reorganize dependencies across multiple packages
fulleni Jul 23, 2025
6da9ca6
style: remove unnecessary line break in import statement
fulleni Jul 23, 2025
2389a64
ci: update CD workflow and dependencies
fulleni Jul 23, 2025
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
14 changes: 13 additions & 1 deletion .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,16 @@ updates:
schedule:
interval: "daily"
ignore:
- dependency-name: "ht_*"
- dependency-name: "auth_api"
- dependency-name: "auth_client"
- dependency-name: "auth_inmemory"
- dependency-name: "auth_repository"
- dependency-name: "data_api"
- dependency-name: "data_client"
- dependency-name: "data_inmemory"
- dependency-name: "data_repository"
- dependency-name: "http_client"
- dependency-name: "kv_storage_service"
- dependency-name: "kv_storage_shared_preferences"
- dependency-name: "core"
- dependency-name: "ui_kit"
8 changes: 4 additions & 4 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: deploy
name: cd

# Run this workflow when a new release is published
on:
Expand All @@ -11,7 +11,7 @@ jobs:
steps:
# 1. Checkout the repository code
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

# 2. Setup Flutter SDK
- name: Setup Flutter
Expand All @@ -25,11 +25,11 @@ jobs:

# 4. Build the Flutter web app
- name: Build Web App
run: flutter build web --release --base-href /ht-main/
run: flutter build web --release --base-href /flutter-news-app-mobile-client-full-source-code/

# 5. Deploy the built app to GitHub Pages
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build/web
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ht_main
name: ci

concurrency:
group: $-$
Expand Down
74 changes: 44 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,106 @@
# 📱✨ ht_main
# The Complete Flutter News App - Full Source Code

![coverage: percentage](https://img.shields.io/badge/coverage-XX-green)
[![Demo: Live](https://img.shields.io/badge/Demo-Live-orange)](https://headlines-toolkit.github.io/ht-main/)
[![Demo: Live](https://img.shields.io/badge/Demo-Live-orange)](https://flutter-news-app-full-source-code.github.io/flutter-news-app-mobile-client-full-source-code/)
[![style: very good analysis](https://img.shields.io/badge/style-very_good_analysis-B22C89.svg)](https://pub.dev/packages/very_good_analysis)
[![License: PolyForm Free Trial](https://img.shields.io/badge/License-PolyForm%20Free%20Trial-blue)](https://polyformproject.org/licenses/free-trial/1.0.0)

`ht_main` is a flutter mobile application that serves as both a powerful, fully functional news application ready for deployment, and an exceptionally robust starter kit, architected for easy extension and customization. It is a key component of the [Headlines Toolkit](https://github.com/headlines-toolkit), an ecosystem that also includes a [Dart Frog backend API](https://github.com/headlines-toolkit/ht-api) and a [web-based content dashboard](https://github.com/headlines-toolkit/ht-dashboard).
This is a complete and fully-functional Flutter news application. It gives you everything you need to launch your own news app on the App Store and Google Play, right out of the box. It is a key component of the [**Flutter News App - Full Source Code Toolkit**](https://github.com/flutter-news-app-full-source-code), an ecosystem that also includes a [Dart Frog backend API](https://github.com/flutter-news-app-full-source-code/flutter-news-app-api-server-full-source-code) and a [web-based content dashboard](https://github.com/flutter-news-app-full-source-code/flutter-news-app-web-dashboard-full-source-code).

## ⭐ Features & Benefits
## ⭐ Everything You Get, Ready to Go

`ht_main` comes packed with features to accelerate your development and delight your users:
This app comes packed with all the features you need to launch a professional news application.

#### 📰 **Dynamic & Engaging Headlines Feed**
Experience a beautifully crafted, infinitely scrolling news feed. It's highly performant and ready for your content.
* **Benefit for you:** Save months of UI/UX development and complex state management. Get a production-quality feed system instantly! ⏱️
* Display news in a beautiful, performant, infinitely scrolling feed.
* Strategically display in-feed messages to drive user actions. Show calls-to-action like 'Create an Account' to anonymous users or 'Upgrade to Premium' to authenticated users, all based on configurable rules.
> **Your Advantage:** You get a production-quality feed system instantly. Skip the months of complex UI work and state management. ⏱️

#### 🔍 **Advanced Content Filtering & Search**
Empower users with intuitive filtering for headlines by categories, sources, and countries. A dedicated search page helps users find exactly what they're looking for.
* **Benefit for you:** Offer powerful content discovery tools that significantly enhance user engagement and satisfaction. 🎯
* Let users filter headlines by categories, sources, and countries.
* Includes a dedicated search page to help users find specific content quickly.
> **Your Advantage:** Give your users powerful content discovery tools that keep them engaged and coming back for more. 🎯

#### 🔐 **Robust User Authentication**
Secure and flexible authentication flows are built-in:
* 📧 **Email + Code (Passwordless) Sign-In:** Modern and secure.
* 👤 **Anonymous Sign-In:** Allow users to explore before committing.
* 🔗 **Account Linking:** Seamlessly convert anonymous users to registered accounts, preserving all their personalized settings, content preferences, and saved headlines.
* **Benefit for you:** Complex security and user management handled, including data migration during account linking, letting you focus on features. ✅
> **Your Advantage:** All the complex security and user management is already done for you, including data migration when users link their accounts. ✅

#### 🧑‍🎨 **Personalized User Accounts & Preferences**
Users can tailor their experience:
* **Content Preferences:** Follow/unfollow categories, sources, and countries.
* **Saved Headlines:** Bookmark articles for easy access later.
* **Benefit for you:** A strong foundation for personalization, driving user retention and creating a sticky app experience. ❤️
> **Your Advantage:** Built-in personalization features that drive user retention and create a sticky app experience. ❤️

#### ⚙️ **Customizable App Settings**
Offer users control over their app experience:
* **Appearance:** Light/Dark/System themes, accent colors (via FlexColorScheme), font choices, and text scaling.
* **Feed Display:** Customize how headlines are presented.
* **Benefit for you:** Provide a premium, adaptable user experience that caters to individual needs. 🔧
> **Your Advantage:** Deliver a premium, adaptable user experience that caters to individual needs without writing any code. 🔧

#### 📱 **Adaptive UI for All Screens**
Built with `flutter_adaptive_scaffold`, `ht_main` offers responsive navigation and layouts that look great on both phones and tablets.
* **Benefit for you:** Deliver a consistent and optimized UX across a wide range of devices effortlessly. ↔️
Built with `flutter_adaptive_scaffold`, the app offers responsive navigation and layouts that look great on both phones and tablets.
> **Your Advantage:** Deliver a consistent and optimized UX across a wide range of devices effortlessly. ↔️

#### 🏗️ **Clean & Modern Architecture**
Developed with best practices for a maintainable and scalable codebase:
* **Flutter & Dart:** Cutting-edge mobile development.
* **BLoC Pattern:** Predictable and robust state management.
* **GoRouter:** Well-structured and powerful navigation.
* **Benefit for you:** An easy-to-understand, extendable, and testable foundation for your project. 📈
> **Your Advantage:** The app is built on a clean, modern architecture that's easy to understand and maintain. It's solid and built to last. 📈

#### ⚙️ **Flexible Environment Configuration**
Easily switch between development (in-memory data or local API) and production environments with a simple code change. This empowers rapid prototyping, robust testing, and seamless deployment.
* **Benefit for you:** Accelerate your development cycle and ensure your app is always ready for any deployment scenario. 🚀
> **Your Advantage:** A flexible setup that speeds up your development cycle and makes deployment simple. 🚀

#### 🌍 **Localization Ready**
Fully internationalized with working English and Arabic localizations (`.arb` files). Adding more languages is straightforward.
* **Benefit for you:** Easily adapt your application for a global audience. 🌐
> **Your Advantage:** Easily adapt your application for a global audience and tap into new markets. 🌐

---

## 🔑 Access and Licensing
## 🔑 Licensing

`ht-main` is source-available as part of the Headlines Toolkit ecosystem.
This app is source-available and licensed under the [PolyForm Free Trial 1.0.0](LICENSE). This lets you try out the full source code before you buy.

For a commercial license to build and distribute your app, please visit the main [**Flutter News App - Full Source Code Toolkit**](https://github.com/flutter-news-app-full-source-code) organization.

To acquire a commercial license for building unlimited news applications, please visit
the [Headlines Toolkit GitHub organization page](https://github.com/headlines-toolkit)
for more details.

---

## 🚀 Getting Started
## 🚀 Getting Started & Running Locally

1. **Ensure Flutter is installed.** (See [Flutter documentation](https://flutter.dev/docs/get-started/install))
2. **Clone the repository:**
```bash
git clone https://github.com/headlines-toolkit/ht-main.git
cd ht-main
git clone https://github.com/flutter-news-app-full-source-code/flutter-news-app-mobile-client-full-source-code.git
cd flutter-news-app-mobile-client-full-source-code
```
3. **Get dependencies:**
```bash
flutter pub get
```
4. **Run the app:**
```bash
flutter run
```
*(Note: For full functionality, ensure the `ht-api` backend service is running and accessible.)*

### Running the App

To run the app, first select your desired environment in `lib/main.dart`:

```dart
// lib/main.dart

// Use `AppEnvironment.demo` to run with in-memory data (no API needed).
// Use `AppEnvironment.development` to connect to a local backend API.
const appEnvironment = AppEnvironment.demo;
```

Then, run the app from your terminal:
```bash
flutter run
```
*(Note: For `development` environment, ensure the [backend service](https://github.com/flutter-news-app-full-source-code/flutter-news-app-api-server-full-source-code) is running.)*

---

Expand All @@ -96,4 +111,3 @@ This project aims for high test coverage to ensure quality and reliability.
* Run tests with:
```bash
flutter test
```
4 changes: 2 additions & 2 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ plugins {
}

android {
namespace = "com.example.ht_main"
namespace = "com.example.flutter_news_app_mobile_client_full_source_code"
compileSdk = flutter.compileSdkVersion
ndkVersion = "29.0.13113456"

Expand All @@ -24,7 +24,7 @@ android {

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.ht_main"
applicationId = "com.example.flutter_news_app_mobile_client_full_source_code"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 24
Expand Down
6 changes: 3 additions & 3 deletions android/app/google-services.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"project_info": {
"project_number": "420644261437",
"project_id": "headlines-toolkit",
"storage_bucket": "headlines-toolkit.firebasestorage.app"
"project_id": "flutter-news-app-full-source-code",
"storage_bucket": "flutter-news-app-full-source-code.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:420644261437:android:3fa3052f883bf86958a454",
"android_client_info": {
"package_name": "com.example.ht_main"
"package_name": "com.example.flutter_news_app_mobile_client_full_source_code"
}
},
"oauth_client": [],
Expand Down
4 changes: 2 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="ht_main"
android:label="flutter_news_app_mobile_client_full_source_code"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
<activity
Expand Down Expand Up @@ -30,7 +30,7 @@
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<!-- Accepts URIs that begin with your dynamic link domain -->
<data android:scheme="https" android:host="htmain.page.link" />
<data android:scheme="https" android:host="flutter-news-app-full-source-code.page.link" />
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.example.ht_main
package com.example.flutter_news_app_mobile_client_full_source_code

import io.flutter.embedding.android.FlutterActivity

Expand Down
45 changes: 22 additions & 23 deletions lib/account/bloc/account_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import 'dart:async';

import 'package:auth_repository/auth_repository.dart';
import 'package:bloc/bloc.dart';
import 'package:core/core.dart';
import 'package:data_repository/data_repository.dart';
import 'package:equatable/equatable.dart';
import 'package:ht_auth_repository/ht_auth_repository.dart';
import 'package:ht_data_repository/ht_data_repository.dart';
import 'package:ht_main/app/config/config.dart' as local_config;
import 'package:ht_shared/ht_shared.dart';
import 'package:flutter_news_app_mobile_client_full_source_code/app/config/config.dart'
as local_config;
import 'package:logging/logging.dart';

part 'account_event.dart';
part 'account_state.dart';

class AccountBloc extends Bloc<AccountEvent, AccountState> {
AccountBloc({
required HtAuthRepository authenticationRepository,
required HtDataRepository<UserContentPreferences>
required AuthRepository authenticationRepository,
required DataRepository<UserContentPreferences>
userContentPreferencesRepository,
required local_config.AppEnvironment environment,
Logger? logger,
Expand All @@ -23,7 +24,7 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
_environment = environment,
_logger = logger ?? Logger('AccountBloc'),
super(const AccountState()) {
// Listen to user changes from HtAuthRepository
// Listen to user changes from AuthRepository
_userSubscription = _authenticationRepository.authStateChanges.listen((
user,
) {
Expand All @@ -39,8 +40,8 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
on<AccountClearUserPreferences>(_onAccountClearUserPreferences);
}

final HtAuthRepository _authenticationRepository;
final HtDataRepository<UserContentPreferences>
final AuthRepository _authenticationRepository;
final DataRepository<UserContentPreferences>
_userContentPreferencesRepository;
final local_config.AppEnvironment _environment;
final Logger _logger;
Expand Down Expand Up @@ -149,9 +150,9 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
clearError: true,
),
);
} on HtHttpException catch (e) {
} on HttpException catch (e) {
_logger.severe(
'Failed to create default preferences with HtHttpException: $e',
'Failed to create default preferences with HttpException: $e',
);
emit(state.copyWith(status: AccountStatus.failure, error: e));
} catch (e, st) {
Expand All @@ -169,9 +170,9 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
),
);
}
} on HtHttpException catch (e) {
} on HttpException catch (e) {
_logger.severe(
'AccountLoadUserPreferences failed with HtHttpException: $e',
'AccountLoadUserPreferences failed with HttpException: $e',
);
emit(state.copyWith(status: AccountStatus.failure, error: e));
} catch (e, st) {
Expand Down Expand Up @@ -227,9 +228,9 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
clearError: true,
),
);
} on HtHttpException catch (e) {
} on HttpException catch (e) {
_logger.severe(
'AccountSaveHeadlineToggled failed with HtHttpException: $e',
'AccountSaveHeadlineToggled failed with HttpException: $e',
);
emit(state.copyWith(status: AccountStatus.failure, error: e));
} catch (e, st) {
Expand Down Expand Up @@ -284,10 +285,8 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
clearError: true,
),
);
} on HtHttpException catch (e) {
_logger.severe(
'AccountFollowTopicToggled failed with HtHttpException: $e',
);
} on HttpException catch (e) {
_logger.severe('AccountFollowTopicToggled failed with HttpException: $e');
emit(state.copyWith(status: AccountStatus.failure, error: e));
} catch (e, st) {
_logger.severe(
Expand Down Expand Up @@ -344,9 +343,9 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
clearError: true,
),
);
} on HtHttpException catch (e) {
} on HttpException catch (e) {
_logger.severe(
'AccountFollowSourceToggled failed with HtHttpException: $e',
'AccountFollowSourceToggled failed with HttpException: $e',
);
emit(state.copyWith(status: AccountStatus.failure, error: e));
} catch (e, st) {
Expand Down Expand Up @@ -392,9 +391,9 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
clearError: true,
),
);
} on HtHttpException catch (e) {
} on HttpException catch (e) {
_logger.severe(
'AccountClearUserPreferences failed with HtHttpException: $e',
'AccountClearUserPreferences failed with HttpException: $e',
);
emit(state.copyWith(status: AccountStatus.failure, error: e));
} catch (e, st) {
Expand Down
4 changes: 2 additions & 2 deletions lib/account/bloc/account_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ class AccountState extends Equatable {
final AccountStatus status;
final User? user;
final UserContentPreferences? preferences;
final HtHttpException? error;
final HttpException? error;

AccountState copyWith({
AccountStatus? status,
User? user,
UserContentPreferences? preferences,
HtHttpException? error,
HttpException? error,
bool clearUser = false,
bool clearPreferences = false,
bool clearError = false,
Expand Down
Loading
Loading