Compare commits
3 Commits
dev
...
about-page
Author | SHA1 | Date | |
---|---|---|---|
|
a418844534 | ||
|
051ce4680a | ||
|
0023f1a7c5 |
322
dialer/lib/features/about/about.dart
Normal file
322
dialer/lib/features/about/about.dart
Normal file
@ -0,0 +1,322 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class AboutPage extends StatefulWidget {
|
||||
const AboutPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AboutPageState createState() => _AboutPageState();
|
||||
}
|
||||
|
||||
class _AboutPageState extends State<AboutPage> {
|
||||
String _version = '';
|
||||
String _buildNumber = '';
|
||||
bool _isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadPackageInfo();
|
||||
}
|
||||
|
||||
Future<void> _loadPackageInfo() async {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
setState(() {
|
||||
_version = packageInfo.version;
|
||||
_buildNumber = packageInfo.buildNumber;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _launchURL(String url) async {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} else {
|
||||
throw 'Could not launch $url';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: AppBar(
|
||||
title: const Text('About'),
|
||||
backgroundColor: Colors.black,
|
||||
elevation: 0,
|
||||
),
|
||||
body: _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// App Logo and Name
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: 100,
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.phone,
|
||||
size: 60,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
'Icing Dialer',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Version $_version (Build $_buildNumber)',
|
||||
style: TextStyle(
|
||||
color: Colors.grey[400],
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
// App Description
|
||||
const _SectionHeader(title: 'About This App'),
|
||||
const _ContentCard(
|
||||
child: Text(
|
||||
'Icing Dialer is a secure and privacy-focused phone dialer application '
|
||||
'designed to provide a modern, user-friendly interface for making calls, '
|
||||
'managing contacts, and accessing your call history. With features like '
|
||||
'contact obfuscation and encryption protocols, your communication remains '
|
||||
'private and secure.',
|
||||
style: TextStyle(color: Colors.white, height: 1.5),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Features
|
||||
const _SectionHeader(title: 'Key Features'),
|
||||
const _ContentCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_FeatureItem(
|
||||
icon: Icons.phone,
|
||||
title: 'Intuitive Calling Interface',
|
||||
description: 'Easy-to-use dialer with quick access to frequent contacts.',
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
_FeatureItem(
|
||||
icon: Icons.lock,
|
||||
title: 'Secure Communications',
|
||||
description: 'End-to-end encrypted calls with the Icing protocol.',
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
_FeatureItem(
|
||||
icon: Icons.history,
|
||||
title: 'Comprehensive Call History',
|
||||
description: 'View, filter, and manage your recent calls.',
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
_FeatureItem(
|
||||
icon: Icons.contacts,
|
||||
title: 'Advanced Contact Management',
|
||||
description: 'Organize, share, and secure your contacts.',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Support & Privacy
|
||||
const _SectionHeader(title: 'Support & Privacy'),
|
||||
_ContentCard(
|
||||
child: Column(
|
||||
children: [
|
||||
_LinkButton(
|
||||
icon: Icons.help_outline,
|
||||
text: 'Help & Support',
|
||||
onTap: () => _launchURL('https://icing.org/support'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_LinkButton(
|
||||
icon: Icons.privacy_tip_outlined,
|
||||
text: 'Privacy Policy',
|
||||
onTap: () => _launchURL('https://icing.org/privacy'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_LinkButton(
|
||||
icon: Icons.description_outlined,
|
||||
text: 'Terms of Service',
|
||||
onTap: () => _launchURL('https://icing.org/terms'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Credits
|
||||
const _SectionHeader(title: 'Credits'),
|
||||
const _ContentCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Developed by Icing Team',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
'This application utilizes open-source libraries and follows best '
|
||||
'practices for secure software development.',
|
||||
style: TextStyle(color: Colors.white70, height: 1.5),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Text(
|
||||
'© 2025 Icing Organization. All Rights Reserved.',
|
||||
style: TextStyle(color: Colors.grey, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SectionHeader extends StatelessWidget {
|
||||
final String title;
|
||||
|
||||
const _SectionHeader({Key? key, required this.title}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.blue,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ContentCard extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const _ContentCard({Key? key, required this.child}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[900],
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _FeatureItem extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final String description;
|
||||
|
||||
const _FeatureItem({
|
||||
Key? key,
|
||||
required this.icon,
|
||||
required this.title,
|
||||
required this.description,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(icon, color: Colors.blue, size: 20),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
description,
|
||||
style: const TextStyle(color: Colors.white70),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LinkButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String text;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _LinkButton({
|
||||
Key? key,
|
||||
required this.icon,
|
||||
required this.text,
|
||||
required this.onTap,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: Colors.blue),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
text,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: Colors.white70,
|
||||
size: 16,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import 'package:dialer/features/settings/settings.dart';
|
||||
import '../../services/contact_service.dart';
|
||||
import 'package:dialer/features/voicemail/voicemail_page.dart';
|
||||
import '../contacts/widgets/contact_modal.dart';
|
||||
import 'package:dialer/features/about/about.dart'; // Add this import
|
||||
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage>
|
||||
@ -233,6 +234,10 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
value: 'settings',
|
||||
child: Text('Settings'),
|
||||
),
|
||||
const PopupMenuItem<String>( // Add About menu item
|
||||
value: 'about',
|
||||
child: Text('About'),
|
||||
),
|
||||
],
|
||||
onSelected: (String value) {
|
||||
if (value == 'settings') {
|
||||
@ -241,6 +246,12 @@ class _MyHomePageState extends State<MyHomePage>
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SettingsPage()),
|
||||
);
|
||||
} else if (value == 'about') { // Handle About selection
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const AboutPage()),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
@ -55,6 +55,7 @@ dependencies:
|
||||
encrypt: ^5.0.3
|
||||
uuid: ^4.5.1
|
||||
provider: ^6.1.2
|
||||
package_info_plus: ^8.3.0
|
||||
|
||||
intl: any
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user