Compare commits
10 Commits
7f1093eea0
...
9dc42635d0
Author | SHA1 | Date |
---|---|---|
Özcan Oğuz | 9dc42635d0 | 3 years ago |
Özcan Oğuz | d47ba1fe92 | 3 years ago |
Özcan Oğuz | c459058fb2 | 3 years ago |
Özcan Oğuz | 0a543740a2 | 3 years ago |
Özcan Oğuz | 1d08cdb1d7 | 3 years ago |
Özcan Oğuz | 7334bcc08f | 3 years ago |
Özcan Oğuz | 8495acae38 | 3 years ago |
Özcan Oğuz | b89f3c4d42 | 3 years ago |
Özcan Oğuz | 92d7f562a7 | 3 years ago |
Özcan Oğuz | cae08741b9 | 3 years ago |
@ -0,0 +1,48 @@ |
||||
# Miscellaneous |
||||
*.class |
||||
*.log |
||||
*.pyc |
||||
*.swp |
||||
.DS_Store |
||||
.atom/ |
||||
.buildlog/ |
||||
.history |
||||
.svn/ |
||||
|
||||
# IntelliJ related |
||||
*.iml |
||||
*.ipr |
||||
*.iws |
||||
.idea/ |
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in |
||||
# VS Code which you may wish to be included in version control, so this line |
||||
# is commented out by default. |
||||
#.vscode/ |
||||
|
||||
# Flutter/Dart/Pub related |
||||
**/doc/api/ |
||||
**/ios/Flutter/.last_build_id |
||||
.dart_tool/ |
||||
.flutter-plugins |
||||
.flutter-plugins-dependencies |
||||
.packages |
||||
.pub-cache/ |
||||
.pub/ |
||||
/build/ |
||||
|
||||
# Web related |
||||
lib/generated_plugin_registrant.dart |
||||
|
||||
# Symbolication related |
||||
app.*.symbols |
||||
|
||||
# Obfuscation related |
||||
app.*.map.json |
||||
|
||||
# Android Studio will place build artifacts here |
||||
/android/app/debug |
||||
/android/app/profile |
||||
/android/app/release |
||||
|
||||
flutter_native_splash.yaml |
@ -0,0 +1,10 @@ |
||||
# This file tracks properties of this Flutter project. |
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc. |
||||
# |
||||
# This file should be version controlled and should not be manually edited. |
||||
|
||||
version: |
||||
revision: b5017bf8de877083978bfeb1874d236c3fc83029 |
||||
channel: beta |
||||
|
||||
project_type: app |
@ -0,0 +1,4 @@ |
||||
# 0.1.1 |
||||
|
||||
- Beta version of the application. |
||||
- Add video player for videos. |
After Width: | Height: | Size: 9.6 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 70 B |
@ -1,12 +1,9 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- Modify this file to customize your launch splash screen --> |
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="?android:colorBackground" /> |
||||
|
||||
<!-- You can insert your own image assets here --> |
||||
<!-- <item> |
||||
<bitmap |
||||
android:gravity="center" |
||||
android:src="@mipmap/launch_image" /> |
||||
</item> --> |
||||
</layer-list> |
||||
<item> |
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/> |
||||
</item> |
||||
<item> |
||||
<bitmap android:gravity="clip_horizontal" android:src="@drawable/splash"/> |
||||
</item> |
||||
</layer-list> |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 70 B |
@ -1,12 +1,9 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- Modify this file to customize your launch splash screen --> |
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
||||
<item android:drawable="@android:color/white" /> |
||||
|
||||
<!-- You can insert your own image assets here --> |
||||
<!-- <item> |
||||
<bitmap |
||||
android:gravity="center" |
||||
android:src="@mipmap/launch_image" /> |
||||
</item> --> |
||||
</layer-list> |
||||
<item> |
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/> |
||||
</item> |
||||
<item> |
||||
<bitmap android:gravity="clip_horizontal" android:src="@drawable/splash"/> |
||||
</item> |
||||
</layer-list> |
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,165 @@ |
||||
[ |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438797000, |
||||
"id": "e7a673e9-86eb-4572-936f-2882b0183cdc", |
||||
"status": "seen", |
||||
"text": "https://flyer.chat", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438795000, |
||||
"id": "e7a673e9-86eb-4572-936f-2882b0183cda", |
||||
"status": "seen", |
||||
"text": "Dolore labore ipsum aspernatur. Omnis minima reprehenderit perspiciatis sunt rerum facilis consequatur omnis. Rerum totam est eos dolores quia qui aut. Rerum aperiam alias placeat odit non enim corporis unde molestiae. Aspernatur unde praesentium eum ut laudantium ea enim.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438794000, |
||||
"id": "dc1a5e87-bd4e-46b0-9cb4-7d9abeda5ef8", |
||||
"status": "seen", |
||||
"text": "Ut modi corporis consequuntur dolorem omnis asperiores unde voluptatem et.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438793000, |
||||
"id": "2a202811-7d48-4ae9-8323-d764a56031dc", |
||||
"status": "seen", |
||||
"text": "Voluptatem voluptatum eos aut voluptatem occaecati. Quia ducimus vero molestiae molestiae illum illo nisi autem. Labore consectetur expedita illum consequatur inventore consequatur quasi voluptatem. Perspiciatis ut reprehenderit officiis animi voluptas.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Daria", |
||||
"id": "06c33e8b-e835-4736-80f4-63f44b66666c", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/33809426?v=4" |
||||
}, |
||||
"createdAt": 1598438792000, |
||||
"id": "0371b8f4-314a-448e-85ba-9c7dc5ed7a1e", |
||||
"status": "seen", |
||||
"text": "Qui ut nihil facilis quos.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438791000, |
||||
"id": "db334c22-1fc4-4951-86b2-1eb7f7262743", |
||||
"status": "seen", |
||||
"text": "Voluptatem ducimus quo vel sunt. Vitae illum recusandae fuga eum adipisci cumque nam dolor. Aut quia et ducimus a et voluptatibus quo saepe. Vel qui ipsum assumenda quibusdam necessitatibus. Et omnis consectetur ad quod fugiat placeat omnis eligendi aut. Deleniti aspernatur corrupti beatae est et cumque architecto cumque et.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Daria", |
||||
"id": "06c33e8b-e835-4736-80f4-63f44b66666c", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/33809426?v=4" |
||||
}, |
||||
"createdAt": 1598438790000, |
||||
"id": "f61a1924-e043-409f-9051-78ebfc68507a", |
||||
"status": "seen", |
||||
"text": "Est maxime accusantium commodi voluptatem sed. Ut nemo vero ut voluptas qui. Eaque nulla quia pariatur sed qui iure. Odit expedita voluptas quia consequuntur consequatur qui laudantium. Iusto ut voluptatem. Omnis et eos asperiores modi totam quisquam nemo.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Daria", |
||||
"id": "06c33e8b-e835-4736-80f4-63f44b66666c", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/33809426?v=4" |
||||
}, |
||||
"createdAt": 1598438789000, |
||||
"id": "d46ffcb1-9340-4c60-8b8c-c9d17539b0c7", |
||||
"status": "seen", |
||||
"text": "Fugit sed tenetur eaque perferendis est impedit.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438788000, |
||||
"id": "b23e5907-6d8b-4134-8cf3-c6dd34fc42d2", |
||||
"status": "seen", |
||||
"text": "Hic iure corrupti aut delectus tempore.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Daria", |
||||
"id": "06c33e8b-e835-4736-80f4-63f44b66666c", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/33809426?v=4" |
||||
}, |
||||
"createdAt": 1598438787000, |
||||
"id": "83093c75-2efb-47bc-84d6-37dbc53bb5de", |
||||
"status": "seen", |
||||
"text": "Doloremque dolor aliquam totam dolor suscipit qui.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438786000, |
||||
"id": "8fa70836-3309-4d09-a777-4d9603e1f123", |
||||
"status": "seen", |
||||
"text": "Architecto quaerat nulla ipsa facilis cum quasi fuga voluptate.", |
||||
"type": "text" |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438785000, |
||||
"height": 600, |
||||
"id": "8fa70836-3309-4d09-a777-4d9603e1f124", |
||||
"name": "image", |
||||
"size": 59645, |
||||
"status": "seen", |
||||
"type": "image", |
||||
"uri": "https://hcti.io/v1/image/c1ea794e-32c7-4516-bd0f-8b835e8a2f2e", |
||||
"width": 1128 |
||||
}, |
||||
{ |
||||
"author": { |
||||
"firstName": "Alex", |
||||
"id": "b4878b96-efbc-479a-8291-474ef323dec7", |
||||
"imageUrl": "https://avatars.githubusercontent.com/u/14123304?v=4" |
||||
}, |
||||
"createdAt": 1598438784000, |
||||
"id": "8fa70836-3309-4d09-a777-4d9603e1f125", |
||||
"mimeType": "image/jpg", |
||||
"name": "image.jpg", |
||||
"size": 59645, |
||||
"status": "seen", |
||||
"type": "file", |
||||
"uri": "https://hcti.io/v1/image/c1ea794e-32c7-4516-bd0f-8b835e8a2f2e" |
||||
} |
||||
] |
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,21 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"filename" : "background.png", |
||||
"idiom" : "universal", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"scale" : "3x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"author" : "xcode", |
||||
"version" : 1 |
||||
} |
||||
} |
After Width: | Height: | Size: 70 B |
@ -1,23 +1,23 @@ |
||||
{ |
||||
"images" : [ |
||||
{ |
||||
"idiom" : "universal", |
||||
"filename" : "LaunchImage.png", |
||||
"idiom" : "universal", |
||||
"scale" : "1x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"filename" : "LaunchImage@2x.png", |
||||
"idiom" : "universal", |
||||
"scale" : "2x" |
||||
}, |
||||
{ |
||||
"idiom" : "universal", |
||||
"filename" : "LaunchImage@3x.png", |
||||
"idiom" : "universal", |
||||
"scale" : "3x" |
||||
} |
||||
], |
||||
"info" : { |
||||
"version" : 1, |
||||
"author" : "xcode" |
||||
"author" : "xcode", |
||||
"version" : 1 |
||||
} |
||||
} |
||||
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 25 KiB |
@ -1,45 +1,47 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundleDevelopmentRegion</key> |
||||
<string>$(DEVELOPMENT_LANGUAGE)</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>$(EXECUTABLE_NAME)</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
||||
<key>CFBundleInfoDictionaryVersion</key> |
||||
<string>6.0</string> |
||||
<key>CFBundleName</key> |
||||
<string>ozgurkon_app</string> |
||||
<key>CFBundlePackageType</key> |
||||
<string>APPL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>$(FLUTTER_BUILD_NAME)</string> |
||||
<key>CFBundleSignature</key> |
||||
<string>????</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>$(FLUTTER_BUILD_NUMBER)</string> |
||||
<key>LSRequiresIPhoneOS</key> |
||||
<true/> |
||||
<key>UILaunchStoryboardName</key> |
||||
<string>LaunchScreen</string> |
||||
<key>UIMainStoryboardFile</key> |
||||
<string>Main</string> |
||||
<key>UISupportedInterfaceOrientations</key> |
||||
<array> |
||||
<string>UIInterfaceOrientationPortrait</string> |
||||
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
</array> |
||||
<key>UISupportedInterfaceOrientations~ipad</key> |
||||
<array> |
||||
<string>UIInterfaceOrientationPortrait</string> |
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
||||
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
</array> |
||||
<key>UIViewControllerBasedStatusBarAppearance</key> |
||||
<false/> |
||||
</dict> |
||||
</plist> |
||||
<dict> |
||||
<key>CFBundleDevelopmentRegion</key> |
||||
<string>$(DEVELOPMENT_LANGUAGE)</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>$(EXECUTABLE_NAME)</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
||||
<key>CFBundleInfoDictionaryVersion</key> |
||||
<string>6.0</string> |
||||
<key>CFBundleName</key> |
||||
<string>ozgurkon_app</string> |
||||
<key>CFBundlePackageType</key> |
||||
<string>APPL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>$(FLUTTER_BUILD_NAME)</string> |
||||
<key>CFBundleSignature</key> |
||||
<string>????</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>$(FLUTTER_BUILD_NUMBER)</string> |
||||
<key>LSRequiresIPhoneOS</key> |
||||
<true/> |
||||
<key>UILaunchStoryboardName</key> |
||||
<string>LaunchScreen</string> |
||||
<key>UIMainStoryboardFile</key> |
||||
<string>Main</string> |
||||
<key>UISupportedInterfaceOrientations</key> |
||||
<array> |
||||
<string>UIInterfaceOrientationPortrait</string> |
||||
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
</array> |
||||
<key>UISupportedInterfaceOrientations~ipad</key> |
||||
<array> |
||||
<string>UIInterfaceOrientationPortrait</string> |
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string> |
||||
<string>UIInterfaceOrientationLandscapeLeft</string> |
||||
<string>UIInterfaceOrientationLandscapeRight</string> |
||||
</array> |
||||
<key>UIViewControllerBasedStatusBarAppearance</key> |
||||
<false/> |
||||
<key>UIStatusBarHidden</key> |
||||
<false/> |
||||
</dict> |
||||
</plist> |
@ -0,0 +1,38 @@ |
||||
import 'package:get/get.dart'; |
||||
|
||||
class Messages extends Translations { |
||||
@override |
||||
Map<String, Map<String, String>> get keys => { |
||||
'en_US': { |
||||
'chat': 'Chat', |
||||
'live': 'Live', |
||||
'schedule': 'Schedule', |
||||
'videos': 'Videos', |
||||
'about_app': 'About ÖzgürKon app', |
||||
'app_description': 'Android app for ÖzgürKon, Developed in Flutter.', |
||||
'view_readme': 'View README', |
||||
'view_changelog': 'View changelog', |
||||
'view_license': 'View license', |
||||
'contributors': 'Contributors', |
||||
'fs_licenses': 'Free software licenses', |
||||
'loading': "Loading...", |
||||
'next_year': "See you next year!", |
||||
}, |
||||
'tr_TR': { |
||||
'chat': 'Sohbet', |
||||
'live': 'Canlı', |
||||
'schedule': 'Program', |
||||
'videos': 'Videolar', |
||||
'about_app': 'ÖzgürKon uygulaması hakkında', |
||||
'app_description': |
||||
'ÖzgürKon için Android uygulaması, Flutter ile geliştirildi.', |
||||
'view_readme': "README'yi görüntüle", |
||||
'view_changelog': "Değişiklik özetini görüntüle", |
||||
'view_license': 'Lisans', |
||||
'contributors': 'Katkıda bulunanlar', |
||||
'fs_licenses': 'Özgür yazılım lisansları', |
||||
'loading': 'Yükleniyor...', |
||||
'next_year': "Seneye görüşmek üzere!", |
||||
} |
||||
}; |
||||
} |
@ -1,24 +1,78 @@ |
||||
import 'dart:io'; |
||||
import 'dart:convert'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:webview_flutter/webview_flutter.dart'; |
||||
import 'package:flutter/services.dart' show rootBundle; |
||||
import 'package:flutter_chat_types/flutter_chat_types.dart' as types; |
||||
import 'package:flutter_chat_ui/flutter_chat_ui.dart'; |
||||
import 'package:uuid/uuid.dart'; |
||||
|
||||
class ChatPage extends StatefulWidget { |
||||
const ChatPage({Key? key}) : super(key: key); |
||||
|
||||
class WebViewExample extends StatefulWidget { |
||||
@override |
||||
WebViewExampleState createState() => WebViewExampleState(); |
||||
_ChatPageState createState() => _ChatPageState(); |
||||
} |
||||
|
||||
class WebViewExampleState extends State<WebViewExample> { |
||||
class _ChatPageState extends State<ChatPage> { |
||||
List<types.Message> _messages = []; |
||||
final _user = const types.User(id: '06c33e8b-e835-4736-80f4-63f44b66666c'); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
// Enable hybrid composition. |
||||
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); |
||||
_loadMessages(); |
||||
} |
||||
|
||||
void _addMessage(types.Message message) { |
||||
setState(() { |
||||
_messages.insert(0, message); |
||||
}); |
||||
} |
||||
|
||||
void _handlePreviewDataFetched( |
||||
types.TextMessage message, |
||||
types.PreviewData previewData, |
||||
) { |
||||
final index = _messages.indexWhere((element) => element.id == message.id); |
||||
final updatedMessage = _messages[index].copyWith(previewData: previewData); |
||||
|
||||
WidgetsBinding.instance?.addPostFrameCallback((_) { |
||||
setState(() { |
||||
_messages[index] = updatedMessage; |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
void _handleSendPressed(types.PartialText message) { |
||||
final textMessage = types.TextMessage( |
||||
author: _user, |
||||
createdAt: DateTime.now().millisecondsSinceEpoch, |
||||
id: const Uuid().v4(), |
||||
text: message.text, |
||||
); |
||||
|
||||
_addMessage(textMessage); |
||||
} |
||||
|
||||
void _loadMessages() async { |
||||
final response = await rootBundle.loadString('assets/messages.json'); |
||||
final messages = (jsonDecode(response) as List) |
||||
.map((e) => types.Message.fromJson(e as Map<String, dynamic>)) |
||||
.toList(); |
||||
|
||||
setState(() { |
||||
_messages = messages; |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return WebView( |
||||
initialUrl: 'https://kiwiirc.com/client/chat.freenode.net/%23ozgurkon', |
||||
return Scaffold( |
||||
body: Chat( |
||||
messages: _messages, |
||||
onPreviewDataFetched: _handlePreviewDataFetched, |
||||
onSendPressed: _handleSendPressed, |
||||
user: _user, |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
@ -1,28 +1,31 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:video_viewer/video_viewer.dart'; |
||||
import 'package:get/get.dart'; |
||||
import 'package:flutter_svg_provider/flutter_svg_provider.dart'; |
||||
|
||||
class HLSVideoExample extends StatelessWidget { |
||||
class Live extends StatelessWidget { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return FutureBuilder<Map<String, VideoSource>>( |
||||
future: VideoSource.fromM3u8PlaylistUrl( |
||||
"https://sfux-ext.sfux.info/hls/chapter/105/1588724110/1588724110.m3u8", |
||||
formatter: (quality) => |
||||
quality == "Auto" ? "Automatic" : "${quality.split("x").last}p", |
||||
return Container( |
||||
width: double.infinity, |
||||
height: double.infinity, |
||||
decoration: BoxDecoration( |
||||
color: Color(0xFFededed), |
||||
image: DecorationImage( |
||||
image: Svg( |
||||
'assets/flat-mountains.svg', |
||||
), |
||||
alignment: Alignment.bottomCenter, |
||||
), |
||||
), |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
children: [ |
||||
Text( |
||||
'next_year'.tr, |
||||
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700), |
||||
) |
||||
], |
||||
), |
||||
builder: (_, data) { |
||||
return data.hasData |
||||
? VideoViewer( |
||||
source: data.data, |
||||
onFullscreenFixLandscape: true, |
||||
style: VideoViewerStyle( |
||||
thumbnail: Image.network( |
||||
"https://play-lh.googleusercontent.com/aA2iky4PH0REWCcPs9Qym2X7e9koaa1RtY-nKkXQsDVU6Ph25_9GkvVuyhS72bwKhN1P", |
||||
), |
||||
), |
||||
) |
||||
: CircularProgressIndicator(); |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,11 @@ |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:ozgurkon_app/screens/About.dart'; |
||||
|
||||
class Settings extends StatelessWidget { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
body: MyAbout(), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,140 @@ |
||||
import 'dart:async'; |
||||
import 'dart:convert'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:http/http.dart' as http; |
||||
import 'package:get/get.dart'; |
||||
import 'package:fluttericon/entypo_icons.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:better_player/better_player.dart'; |
||||
|
||||
class Video { |
||||
final String uuid; |
||||
final String name; |
||||
final String desc; |
||||
final String speaker; |
||||
final String lang; |
||||
final int duration; |
||||
final String streamURL; |
||||
final String downloadURL; |
||||
|
||||
Video( |
||||
{required this.uuid, |
||||
required this.name, |
||||
required this.desc, |
||||
required this.speaker, |
||||
required this.lang, |
||||
required this.duration, |
||||
required this.streamURL, |
||||
required this.downloadURL}); |
||||
|
||||
factory Video.fromJson(Map<String, dynamic> json) { |
||||
return Video( |
||||
uuid: json['uuid'], |
||||
name: json['name'].split(' | ')[0].split(' by ')[0], |
||||
desc: json['description'], |
||||
speaker: json['name'].split(' | ')[0].split(' by ')[1], |
||||
lang: json['language']['id'], |
||||
duration: json['duration'], |
||||
streamURL: json['files'][0]['fileUrl'], |
||||
downloadURL: json['files'][0]['fileDownloadUrl'], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class VideoView extends StatelessWidget { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return FutureBuilder<Video>( |
||||
future: _fetchVideoDetails(), |
||||
builder: (context, snapshot) { |
||||
if (snapshot.hasData) { |
||||
Video? data = snapshot.data; |
||||
return new Scaffold( |
||||
appBar: AppBar( |
||||
title: Text("Video"), |
||||
), |
||||
body: new SingleChildScrollView( |
||||
child: Column( |
||||
mainAxisAlignment: MainAxisAlignment.start, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: <Widget>[_videoView(data)], |
||||
), |
||||
)); |
||||
} else if (snapshot.hasError) { |
||||
return Text("${snapshot.error}"); |
||||
} |
||||
return Container(child: Row(children: [CircularProgressIndicator()])); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
Future<Video> _fetchVideoDetails() async { |
||||
String uuid = Get.parameters['uuid'] as String; |
||||
final String videoDetailAPI = |
||||
'https://video.ozgurkon.org/api/v1/videos/' + uuid; |
||||
final response = await http.get(Uri.parse(videoDetailAPI)); |
||||
|
||||
if (response.statusCode == 200) { |
||||
var jsonResponse = json.decode(response.body); |
||||
final description = |
||||
await http.get(Uri.parse(videoDetailAPI + '/description')); |
||||
if (description.statusCode == 200) { |
||||
var descriptionResponse = json.decode(description.body); |
||||
jsonResponse['description'] = descriptionResponse['description']; |
||||
} |
||||
return Video.fromJson(jsonResponse); |
||||
} else { |
||||
throw Exception('Failed to load video details from API'); |
||||
} |
||||
} |
||||
|
||||
Card _videoView(data) { |
||||
return Card( |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: <Widget>[ |
||||
AspectRatio( |
||||
aspectRatio: 16 / 9, |
||||
child: BetterPlayer.network( |
||||
data!.streamURL, |
||||
betterPlayerConfiguration: BetterPlayerConfiguration( |
||||
aspectRatio: 16 / 9, |
||||
autoPlay: true, |
||||
), |
||||
), |
||||
), |
||||
ListTile( |
||||
title: Text(data.name), |
||||
subtitle: Text(data.speaker), |
||||
trailing: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[ |
||||
Icon(Entypo.cc), |
||||
Icon(Entypo.cc_by), |
||||
Icon(Entypo.cc_sa) |
||||
]), |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(16.0), |
||||
child: Text( |
||||
data.desc, |
||||
style: TextStyle(color: Colors.black.withOpacity(0.6)), |
||||
), |
||||
), |
||||
Row( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: <Widget>[ |
||||
TextButton( |
||||
child: const Text('DOWNLOAD'), |
||||
onPressed: () { |
||||
Get.toNamed('/videoplayer', arguments: data.streamURL); |
||||
}, |
||||
), |
||||
const SizedBox(width: 8), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,93 @@ |
||||
import 'dart:async'; |
||||
import 'dart:convert'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:http/http.dart' as http; |
||||
import 'package:get/get.dart'; |
||||
|
||||
class VideoList { |
||||
final String uuid; |
||||
final String name; |
||||
final String speaker; |
||||
final String lang; |
||||
final String thumbnail; |
||||
|
||||
VideoList( |
||||
{required this.uuid, |
||||
required this.name, |
||||
required this.speaker, |
||||
required this.lang, |
||||
required this.thumbnail}); |
||||
|
||||
factory VideoList.fromJson(Map<String, dynamic> json) { |
||||
return VideoList( |
||||
uuid: json['uuid'], |
||||
name: json['name'].split(' | ')[0].split(' by ')[0], |
||||
speaker: json['name'].split(' | ')[0].split(' by ')[1], |
||||
lang: json['language']['id'], |
||||
thumbnail: json['thumbnailPath'], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class VideosListView extends StatelessWidget { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return FutureBuilder<List<VideoList>>( |
||||
future: _fetchVideos(), |
||||
builder: (context, snapshot) { |
||||
if (snapshot.hasData) { |
||||
List<VideoList>? data = snapshot.data; |
||||
return _videosListView(data); |
||||
} else if (snapshot.hasError) { |
||||
return Text("${snapshot.error}"); |
||||
} |
||||
return Container( |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [CircularProgressIndicator()])); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
Future<List<VideoList>> _fetchVideos() async { |
||||
final videosFrom2020API = |
||||
'https://video.ozgurkon.org/api/v1/video-channels/ozgurkon2020/videos'; |
||||
final response = await http.get(Uri.parse(videosFrom2020API)); |
||||
|
||||
if (response.statusCode == 200) { |
||||
Map<String, dynamic> jsonResponse = json.decode(response.body); |
||||
List videoList = jsonResponse['data']; |
||||
return videoList.map((job) => new VideoList.fromJson(job)).toList(); |
||||
} else { |
||||
throw Exception('Failed to load videos from API'); |
||||
} |
||||
} |
||||
|
||||
ListView _videosListView(data) { |
||||
return ListView.builder( |
||||
itemCount: data.length, |
||||
itemBuilder: (context, index) { |
||||
return _tile(data[index].uuid, data[index].name, data[index].speaker, |
||||
data[index].thumbnail, data[index].lang); |
||||
}); |
||||
} |
||||
|
||||
ListTile _tile(String uuid, String title, String subtitle, String thumbnail, |
||||
String lang) => |
||||
ListTile( |
||||
title: Text(title, |
||||
style: TextStyle( |
||||
fontWeight: FontWeight.w500, |
||||
fontSize: 20, |
||||
)), |
||||
subtitle: Text(subtitle), |
||||
leading: Image.network('https://video.ozgurkon.org/' + thumbnail), |
||||
trailing: lang == "tr" ? Text("🇹🇷") : Text('🇬🇧'), |
||||
onTap: () { |
||||
print(uuid); |
||||
Get.toNamed('/video/$uuid'); |
||||
}, |
||||
); |
||||
} |
@ -1,14 +1,125 @@ |
||||
import 'package:flutter/material.dart'; |
||||
|
||||
class PlaceholderWidget extends StatelessWidget { |
||||
final Color color; |
||||
import 'dart:async'; |
||||
import 'dart:convert'; |
||||
|
||||
PlaceholderWidget(this.color); |
||||
import 'package:http/http.dart' as http; |
||||
import 'package:get/get.dart'; |
||||
|
||||
class Schedule extends StatelessWidget { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Container( |
||||
color: color, |
||||
return DefaultTabController( |
||||
length: 2, |
||||
child: Scaffold( |
||||
appBar: AppBar( |
||||
flexibleSpace: new Column( |
||||
mainAxisAlignment: MainAxisAlignment.end, |
||||
children: [ |
||||
new TabBar( |
||||
tabs: [ |
||||
new Tab( |
||||
text: "2021-05-29", |
||||
), |
||||
new Tab( |
||||
text: "2021-05-30", |
||||
), |
||||
], |
||||
), |
||||
], |
||||
), |
||||
), |
||||
body: TabBarView( |
||||
children: [ |
||||
Icon(Icons.directions_car), |
||||
Icon(Icons.directions_transit), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class ScheduleItem { |
||||
final String time; |
||||
final String name; |
||||
final List speakers; |
||||
final String lang; |
||||
|
||||
ScheduleItem( |
||||
{required this.time, |
||||
required this.name, |
||||
required this.speakers, |
||||
required this.lang}); |
||||
|
||||
factory ScheduleItem.fromJson(Map<String, dynamic> json) { |
||||
return ScheduleItem( |
||||
time: json['time'], |
||||
name: json['name'], |
||||
speakers: json['speakers'], |
||||
lang: json['lang'], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class ScheduleView extends StatelessWidget { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return FutureBuilder<List<ScheduleItem>>( |
||||
future: _fetchSchedule(), |
||||
builder: (context, snapshot) { |
||||
if (snapshot.hasData) { |
||||
List<ScheduleItem>? data = snapshot.data; |
||||
return _scheduleListView(data); |
||||
} else if (snapshot.hasError) { |
||||
return Text("${snapshot.error}"); |
||||
} |
||||
return Container( |
||||
child: Row( |
||||
mainAxisAlignment: MainAxisAlignment.center, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [CircularProgressIndicator()])); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
Future<List<ScheduleItem>> _fetchSchedule() async { |
||||
final videosFrom2020API = |
||||
'https://video.ozgurkon.org/api/v1/video-channels/ozgurkon2020/videos'; |
||||
final response = await http.get(Uri.parse(videosFrom2020API)); |
||||
|
||||
if (response.statusCode == 200) { |
||||
Map<String, dynamic> jsonResponse = json.decode(response.body); |
||||
List scheduleList = jsonResponse['data']; |
||||
return scheduleList.map((job) => new ScheduleItem.fromJson(job)).toList(); |
||||
} else { |
||||
throw Exception('Failed to load schedule from API'); |
||||
} |
||||
} |
||||
|
||||
ListView _scheduleListView(data) { |
||||
return ListView.builder( |
||||
itemCount: data.length, |
||||
itemBuilder: (context, index) { |
||||
return _tile(data[index].uuid, data[index].name, data[index].speaker, |
||||
data[index].thumbnail, data[index].lang); |
||||
}); |
||||
} |
||||
|
||||
ListTile _tile(String uuid, String title, String subtitle, String thumbnail, |
||||
String lang) => |
||||
ListTile( |
||||
title: Text(title, |
||||
style: TextStyle( |
||||
fontWeight: FontWeight.w500, |
||||
fontSize: 20, |
||||
)), |
||||
subtitle: Text(subtitle), |
||||
leading: Image.network('https://video.ozgurkon.org/' + thumbnail), |
||||
trailing: lang == "tr" ? Text("🇹🇷") : Text('🇬🇧'), |
||||
onTap: () { |
||||
print(uuid); |
||||
Get.toNamed('/video/$uuid'); |
||||
}, |
||||
); |
||||
} |
||||
|
@ -0,0 +1 @@ |
||||
flutter/ephemeral |
@ -0,0 +1,116 @@ |
||||
cmake_minimum_required(VERSION 3.10) |
||||
project(runner LANGUAGES CXX) |
||||
|
||||
set(BINARY_NAME "ozgurkon_app") |
||||
set(APPLICATION_ID "tr.org.oyd.ozgurkon_app") |
||||
|
||||
cmake_policy(SET CMP0063 NEW) |
||||
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") |
||||
|
||||
# Root filesystem for cross-building. |
||||
if(FLUTTER_TARGET_PLATFORM_SYSROOT) |
||||
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) |
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
||||
endif() |
||||
|
||||
# Configure build options. |
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) |
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE |
||||
STRING "Flutter build mode" FORCE) |
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS |
||||
"Debug" "Profile" "Release") |
||||
endif() |
||||
|
||||
# Compilation settings that should be applied to most targets. |
||||
function(APPLY_STANDARD_SETTINGS TARGET) |
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14) |
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror) |
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") |
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") |
||||
endfunction() |
||||
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") |
||||
|
||||
# Flutter library and tool build rules. |
||||
add_subdirectory(${FLUTTER_MANAGED_DIR}) |
||||
|
||||
# System-level dependencies. |
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) |
||||
|
||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") |
||||
|
||||
# Application build |
||||
add_executable(${BINARY_NAME} |
||||
"main.cc" |
||||
"my_application.cc" |
||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" |
||||
) |
||||
apply_standard_settings(${BINARY_NAME}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) |
||||
add_dependencies(${BINARY_NAME} flutter_assemble) |
||||
# Only the install-generated bundle's copy of the executable will launch |
||||
# correctly, since the resources must in the right relative locations. To avoid |
||||
# people trying to run the unbundled copy, put it in a subdirectory instead of |
||||
# the default top-level location. |
||||
set_target_properties(${BINARY_NAME} |
||||
PROPERTIES |
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" |
||||
) |
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding |
||||
# them to the application. |
||||
include(flutter/generated_plugins.cmake) |
||||
|
||||
|
||||
# === Installation === |
||||
# By default, "installing" just makes a relocatable bundle in the build |
||||
# directory. |
||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") |
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) |
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) |
||||
endif() |
||||
|
||||
# Start with a clean build bundle directory every time. |
||||
install(CODE " |
||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") |
||||
" COMPONENT Runtime) |
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") |
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") |
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" |
||||
COMPONENT Runtime) |
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" |
||||
COMPONENT Runtime) |
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" |
||||
COMPONENT Runtime) |
||||
|
||||
if(PLUGIN_BUNDLED_LIBRARIES) |
||||
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" |
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" |
||||
COMPONENT Runtime) |
||||
endif() |
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files |
||||
# from a previous install. |
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets") |
||||
install(CODE " |
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") |
||||
" COMPONENT Runtime) |
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" |
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) |
||||
|
||||
# Install the AOT library on non-Debug builds only. |
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") |
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" |
||||
COMPONENT Runtime) |
||||
endif() |
@ -0,0 +1,87 @@ |
||||
cmake_minimum_required(VERSION 3.10) |
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") |
||||
|
||||
# Configuration provided via flutter tool. |
||||
include(${EPHEMERAL_DIR}/generated_config.cmake) |
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See |
||||
# https://github.com/flutter/flutter/issues/57146. |
||||
|
||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...), |
||||
# which isn't available in 3.10. |
||||
function(list_prepend LIST_NAME PREFIX) |
||||
set(NEW_LIST "") |
||||
foreach(element ${${LIST_NAME}}) |
||||
list(APPEND NEW_LIST "${PREFIX}${element}") |
||||
endforeach(element) |
||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) |
||||
endfunction() |
||||
|
||||
# === Flutter Library === |
||||
# System-level dependencies. |
||||
find_package(PkgConfig REQUIRED) |
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) |
||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) |
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) |
||||
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") |
||||
|
||||
# Published to parent scope for install step. |
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) |
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) |
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) |
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) |
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS |
||||
"fl_basic_message_channel.h" |
||||
"fl_binary_codec.h" |
||||
"fl_binary_messenger.h" |
||||
"fl_dart_project.h" |
||||
"fl_engine.h" |
||||
"fl_json_message_codec.h" |
||||
"fl_json_method_codec.h" |
||||
"fl_message_codec.h" |
||||
"fl_method_call.h" |
||||
"fl_method_channel.h" |
||||
"fl_method_codec.h" |
||||
"fl_method_response.h" |
||||
"fl_plugin_registrar.h" |
||||
"fl_plugin_registry.h" |
||||
"fl_standard_message_codec.h" |
||||
"fl_standard_method_codec.h" |
||||
"fl_string_codec.h" |
||||
"fl_value.h" |
||||
"fl_view.h" |
||||
"flutter_linux.h" |
||||
) |
||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") |
||||
add_library(flutter INTERFACE) |
||||
target_include_directories(flutter INTERFACE |
||||
"${EPHEMERAL_DIR}" |
||||
) |
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") |
||||
target_link_libraries(flutter INTERFACE |
||||
PkgConfig::GTK |
||||
PkgConfig::GLIB |
||||
PkgConfig::GIO |
||||
) |
||||
add_dependencies(flutter flutter_assemble) |
||||
|
||||
# === Flutter tool backend === |
||||
# _phony_ is a non-existent file to force this command to run every time, |
||||
# since currently there's no way to get a full input/output list from the |
||||
# flutter tool. |
||||
add_custom_command( |
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} |
||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_ |
||||
COMMAND ${CMAKE_COMMAND} -E env |
||||
${FLUTTER_TOOL_ENVIRONMENT} |
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" |
||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} |
||||
VERBATIM |
||||
) |
||||
add_custom_target(flutter_assemble DEPENDS |
||||
"${FLUTTER_LIBRARY}" |
||||
${FLUTTER_LIBRARY_HEADERS} |
||||
) |
@ -0,0 +1,13 @@ |
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#include "generated_plugin_registrant.h" |
||||
|
||||
#include <url_launcher_linux/url_launcher_plugin.h> |
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) { |
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = |
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); |
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); |
||||
} |
@ -0,0 +1,13 @@ |
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_ |
||||
#define GENERATED_PLUGIN_REGISTRANT_ |
||||
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
|
||||
// Registers Flutter plugins.
|
||||
void fl_register_plugins(FlPluginRegistry* registry); |
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
@ -0,0 +1,16 @@ |
||||
# |
||||
# Generated file, do not edit. |
||||
# |
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST |
||||
url_launcher_linux |
||||
) |
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES) |
||||
|
||||
foreach(plugin ${FLUTTER_PLUGIN_LIST}) |
||||
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) |
||||
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) |
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) |
||||
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) |
||||
endforeach(plugin) |
@ -0,0 +1,6 @@ |
||||
#include "my_application.h" |
||||
|
||||
int main(int argc, char** argv) { |
||||
g_autoptr(MyApplication) app = my_application_new(); |
||||
return g_application_run(G_APPLICATION(app), argc, argv); |
||||
} |
@ -0,0 +1,105 @@ |
||||
#include "my_application.h" |
||||
|
||||
#include <flutter_linux/flutter_linux.h> |
||||
#ifdef GDK_WINDOWING_X11 |
||||
#include <gdk/gdkx.h> |
||||
#endif |
||||
|
||||
#include "flutter/generated_plugin_registrant.h" |
||||
|
||||
struct _MyApplication { |
||||
GtkApplication parent_instance; |
||||
char** dart_entrypoint_arguments; |
||||
}; |
||||
|
||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) |
||||
|
||||
// Implements GApplication::activate.
|
||||
static void my_application_activate(GApplication* application) { |
||||
MyApplication* self = MY_APPLICATION(application); |
||||
GtkWindow* window = |
||||
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); |
||||
|
||||
// Use a header bar when running in GNOME as this is the common style used
|
||||
// by applications and is the setup most users will be using (e.g. Ubuntu
|
||||
// desktop).
|
||||
// If running on X and not using GNOME then just use a traditional title bar
|
||||
// in case the window manager does more exotic layout, e.g. tiling.
|
||||
// If running on Wayland assume the header bar will work (may need changing
|
||||
// if future cases occur).
|
||||
gboolean use_header_bar = TRUE; |
||||
#ifdef GDK_WINDOWING_X11 |
||||
GdkScreen *screen = gtk_window_get_screen(window); |
||||
if (GDK_IS_X11_SCREEN(screen)) { |
||||
const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); |
||||
if (g_strcmp0(wm_name, "GNOME Shell") != 0) { |
||||
use_header_bar = FALSE; |
||||
} |
||||
} |
||||
#endif |
||||
if (use_header_bar) { |
||||
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); |
||||
gtk_widget_show(GTK_WIDGET(header_bar)); |
||||
gtk_header_bar_set_title(header_bar, "ozgurkon_app"); |
||||
gtk_header_bar_set_show_close_button(header_bar, TRUE); |
||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); |
||||
} |
||||
else { |
||||
gtk_window_set_title(window, "ozgurkon_app"); |
||||
} |
||||
|
||||
gtk_window_set_default_size(window, 1280, 720); |
||||
gtk_widget_show(GTK_WIDGET(window)); |
||||
|
||||
g_autoptr(FlDartProject) project = fl_dart_project_new(); |
||||
fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); |
||||
|
||||
FlView* view = fl_view_new(project); |
||||
gtk_widget_show(GTK_WIDGET(view)); |
||||
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); |
||||
|
||||
fl_register_plugins(FL_PLUGIN_REGISTRY(view)); |
||||
|
||||
gtk_widget_grab_focus(GTK_WIDGET(view)); |
||||
} |
||||
|
||||
// Implements GApplication::local_command_line.
|
||||
static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { |
||||
MyApplication* self = MY_APPLICATION(application); |
||||
// Strip out the first argument as it is the binary name.
|
||||
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); |
||||
|
||||
g_autoptr(GError) error = nullptr; |
||||
if (!g_application_register(application, nullptr, &error)) { |
||||
g_warning("Failed to register: %s", error->message); |
||||
*exit_status = 1; |
||||
return TRUE; |
||||
} |
||||
|
||||
g_application_activate(application); |
||||
*exit_status = 0; |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
// Implements GObject::dispose.
|
||||
static void my_application_dispose(GObject *object) { |
||||
MyApplication* self = MY_APPLICATION(object); |
||||
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); |
||||
G_OBJECT_CLASS(my_application_parent_class)->dispose(object); |
||||
} |
||||
|
||||
static void my_application_class_init(MyApplicationClass* klass) { |
||||
G_APPLICATION_CLASS(klass)->activate = my_application_activate; |
||||
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; |
||||
G_OBJECT_CLASS(klass)->dispose = my_application_dispose; |
||||
} |
||||
|
||||
static void my_application_init(MyApplication* self) {} |
||||
|
||||
MyApplication* my_application_new() { |
||||
return MY_APPLICATION(g_object_new(my_application_get_type(), |
||||
"application-id", APPLICATION_ID, |
||||
"flags", G_APPLICATION_NON_UNIQUE, |
||||
nullptr)); |
||||
} |
@ -0,0 +1,18 @@ |
||||
#ifndef FLUTTER_MY_APPLICATION_H_ |
||||
#define FLUTTER_MY_APPLICATION_H_ |
||||
|
||||
#include <gtk/gtk.h> |
||||
|
||||
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, |
||||
GtkApplication) |
||||
|
||||
/**
|
||||
* my_application_new: |
||||
* |
||||
* Creates a new Flutter-based application. |
||||
* |
||||
* Returns: a new #MyApplication. |
||||
*/ |
||||
MyApplication* my_application_new(); |
||||
|
||||
#endif // FLUTTER_MY_APPLICATION_H_
|
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 25 KiB |
@ -0,0 +1,43 @@ |
||||
body, html { |
||||
margin:0; |
||||
height:100%; |
||||
background: #c03e24; |
||||
background-image: url("img/light-background.png"); |
||||
background-size: 100% 100%; |
||||
} |
||||
|
||||
.center { |
||||
margin: 0; |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
-ms-transform: translate(-50%, -50%); |
||||
transform: translate(-50%, -50%); |
||||
} |
||||
|
||||
.contain { |
||||
display:block; |
||||
width:100%; height:100%; |
||||
object-fit: contain; |
||||
} |
||||
|
||||
.stretch { |
||||
display:block; |
||||
width:100%; height:100%; |
||||
} |
||||
|
||||
.cover { |
||||
display:block; |
||||
width:100%; height:100%; |
||||
object-fit: cover; |
||||
} |
||||
|
||||
@media (prefers-color-scheme: dark) { |
||||
body { |
||||
margin:0; |
||||
height:100%; |
||||
background: #c03e24; |
||||
background-image: url("img/dark-background.png"); |
||||
background-size: 100% 100%; |
||||
} |
||||
} |