social_app_template 1.0.3 social_app_template: ^1.0.3 copied to clipboard
Package to enable you to create a social app in a very quick way.
Package to enable you to create a social app in a very quick way or at least with as most support as possible by using this template with its functions and widgets.
Source code #
Source code is available on GitLab.
Features #
You can use a set of widgets, repositories and models for your social media app.
List with posts #
Currently, this is the root widget of this package. See
Further notes
to explore future widgets that will move into a new root widget.
This list consists of posts that are shown in an infinite list that is paged by 7 items. When user scrolls and reaches the 6th post further posts are loaded automatically.
|
|
A post is implemented by PostInList
widget which shows media, text and creation date of post. As well as post's author image and author name.
When post has media it will show PlatformImageEmbedded
for single images and PlatformImageEmbeddedGallery
for multiple images and PlatformVideoEmbedded
for videos.
Videos are started immediately after they are rendered. You don't need to care about memory issues for long lists with lots of videos. By scrolling videos are paused (when visibility is below 40%), started (when visibility is above 40%) and disposed (when visibility is 0%).
Since a huge amount of users live in regions with slow internet speed or have low Wifi or just want to save mobile data all videos contain PerformanceIndicator. This will show the user if the downloaded quality is at the configured quality. The corresponding switch for configuration will be implemented in the next version.
Getting started #
Add to pubspec.yaml
dependencies:
social_app_template: ^1.0.0
Then in the console of your project folder
flutter pub get
Prerequisites:
environment:
sdk: ">=2.12.0 <3.0.0"
Usage #
You can access widgets and functions provided by this package by SocialApp
interface. Furthermore you have direct access to the most classes as repositories, model classes and services.
Build list with posts #
Please provide sizes to media objects (see
Repositories
for additional information).Otherwise, the list will need some milliseconds to load. First, it will calculate the sizes of images to render.
Provided sizes will allow seamless scrolling with fixed sizes. This also enables caching in appropriate memory size.
You can create a list with posts by calling SocialApp.postList
. You should put the list into a sized container since it is still a list that needs constraints.
You can specify the onRefresh
function for pull down of your list by user.
@override
Widget@build(BuildContext context){
final size = MediaQuery.of(context).size;
final postIds = ['post_0', 'post_1'];
SizedBox(
width: size.width,
height: size.height,
child: SocialApp.postList(
ids: postIds,
onRefresh: _onRefresh,
),
);
List<PlatformPost> _onRefresh() {
return ['post_2', 'post_3'];
}
}
You can use onInitPost
if you like to adjust the post by additional information or to just validate the post before it gets rendered in the list.
@override
Widget build(BuildContext context){
final size = MediaQuery.of(context).size;
final postIds = ['post_0', 'post_1'];
SizedBox(
width: size.width,
height: size.height,
child: SocialApp.postList(
ids: postIds,
onInitPost: _onInitPost,
),
);
Future<PlatformPost?> _onInitPost(PlatformPost post) async {
final postWithMySocialMediaApiDetails = await MySocialMediaApi().getPostDetails();
post.media.addAll(postWithMySocialMediaApiDetails.images);
return post;
}
}
If you wish to have a list with a progress indicator just use SocialApp.postListWithProgress
.
Make sure to provide
progressAlignment
in order to position the progress indicator at the right position.
@override
Widget build(BuildContext context){
final size = MediaQuery.of(context).size;
final postIds = ['post_0', 'post_1'];
final progressAlignment = const Alignment(0.5, -0.85);
SizedBox(
width: size.width,
height: size.height,
child: SocialApp.postListWithProgress(
ids: postIds,
progressAlignment: progressAlignment,
),
);
}
Repositories #
This package provides you the possibility to make all the CRUD operations that you might wish for existing model
classes. The existing database is a very fast database that can also handle storage of millions of objects that also have relations and support very specific querying.
Custom repository #
You can also use
IsarDB.isar
instance to create your own repositories. Just refer to existing code or explore the documentation of Isar.
For the following example of custom repository you will need to run flutter pub run build_runner build
in you project folder.
Therefore temporarily you will need to add following dependencies to your pubspec.yaml
dev_dependencies:
...
isar_generator: ^3.0.5
build_runner: any
In your repository you can use IsarDB.isar
instance to implement all the required CRUD operations.
class MyRepository {
Future<void> create(MyObject){
await IsarDB.isar.writeTxn(
() => IsarDB.isar.myObjects.create(),
);
}
Future<List<MyObject>> getAllById(Id id){
return await IsarDB.isar.myObjects
.where().idEqualsTo(id)
.findAll();
}
}
The model object should have a name for the accessor used in the example above in create
function.
Additionally Id
property is required as the part
that will be generated by your execution of flutter pub run build_runner build
.
part 'my_object.g.dart';
@Collection(accessor: 'myObjects')
class MyObject {
Id? id;
}
After the file my_object.g.dart
is generated you can now pass the created adapter to the root widget.
@override
Widget build(BuildContext context){
final size = MediaQuery.of(context).size;
final postIds = ['post_0', 'post_1'];
SizedBox(
width: size.width,
height: size.height,
child: SocialApp.postList(
ids: postIds,
furtherSchema: [MyObjectSchema],
),
);
}
Repositories of SocialApp Template #
Existing repositories can be called directly without use of the interface SocialApp
as in the following examples.
PlatformPostRepository
#
Repository to manage model objects of PlatformPost
for the posts of your implemented social media.
A PlatformPost
should have an author (see PlatformUserRepository
for more information). Anyway author property is not marked as required. Without a linked author you won't be able to see the profile image and the name of the author of your social media post in the PostInList
widget.
You can include information as urls
, hashtags
, userMentions
or media
by using PlatformPostEntities
.
void main async {
final posts = List.generate(
2,
(index) => PlatformPost.of(
id: '$index',
entities: PlatformPostEntities.of(
postId: '$index',
urls: [
'https://mysocialmedia.web/profile/1234'
],
hashtags: [
'apple',
'fruit',
],
media: [PlatformMedia(
id: 'media_0',
url: 'https://mysocialmedia.web/image/media_0',
)],
)
),
);
await PlatformPostRepository.createAll(posts);
final allCreatedPosts = await PlatformPostRepository.getAll();
/// Should print 2 posts
print(allCreatedPosts.map((post) => '${post.id}\n').toList());
runApp(myApp());
}
PlatformUserRepository
#
Repository to manage model objects of PlatformUser
for the users of your implemented social media.
The model allows you to store the location of user as LocationQuery
(see LocationQueryRepository
for more information).
You should always prefer to create user as embedded object when you call PlatformPostRepository.create
. In the following example author and mentionedUser will be persisted and created in database automatically with the post object.
void main async {
final author = PlatformUser.of(
id: 'user_0',
name: 'user_name',
profileImageUrl: 'https://mysocialmedia.web/images/profile/user_0'
);
final mentionedUser = PlatformUser.of(
id: 'user_1',
name: 'user_name',
profileImageUrl: 'https://mysocialmedia.web/images/profile/user_1'
);
final post = PlatformPost.of(
id: 'post_0',
user: author,
entities: PlatformPostEntities.of(
postId: '$index',
userMentions: [mentionedUser],
)
);
await PlatformPostRepository.create(post);
final users = await PlatformUserRepository.getAllBy(ids: ['user_0','user_1']);
/// Should print 2 users
print(users.map((user) => '${user.id}\n').toList());
runApp(myApp());
}
But you can still create and get users without creating it as embedded object by PlatformUserRepository.create
.
void main async {
final user = PlatformUser.of(
id: 'user_0',
name: 'user_name',
profileImageUrl: 'https://mysocialmedia.web/images/profile/user_0'
);
await PlatformUserRepository.create(user);
final storedUser = await PlatformUserRepository.getAsync('user_0');
/// Should print 1 user
print('${storedUser?.id}\n');
runApp(myApp());
}
LocationQueryRepository
#
Repository to manage model objects of LocationQuery
for the locations of your implemented social media.
The location consists of following properties:
query
-> textual representation of locationlatitude
-> the latitude of locationlongitude
-> the longitude of locationaddress
-> the address of location
The model allows you to store the address of user as MapBoxPlace
object model.
- Since in my own app I get the information about locations from mapbox.com the structure and the name of this object is inspired by mapbox.
- In future releases you will be able to get the addresses from mapbox as well.
void main async {
final location = LocationQuery.of(
id: 0,
query: 'Berlin',
latitude: 52.0,
longitude: 13.0,
address: MapBoxPlace.of(
id: 'place_0',
text: 'Lindenallee',
placeName: 'Zentrum, Berlin',
context: [
MapBoxPlaceContext(
id: 'country_place_0',
mapBoxPlaceId: 'place_0',
text: 'Germany',
),
MapBoxPlaceContext(
id: 'city_place_0',
mapBoxPlaceId: 'place_0',
text: 'Berlin',
),
],
),
);
await LocationQueryRepository.create(location);
final locations = await LocationQueryRepository.getByQueryAsync('Berlin');
/// Should print 1 location
print(locations.map((location) => '${location.query}\n').toList());
runApp(myApp());
}
As mentioned in PlatformUserRepository
you should create embedded objects by their parent object. The same rule is applied to locations.
Thus, also the address as MapBoxPlace
and its contexts as MapBoxPlaceContext
will be persisted and created in database automatically.
For example:
- you use
PlatformUserRepository.create
when you create locations for users - you use correspondingly
PlatformPostRepository.create
when you create locations for users in posts
void main async {
final location = LocationQuery.of(
...
address: MapBoxPlace.of(
...
context: [
MapBoxPlaceContext(
...
),
MapBoxPlaceContext(
...
),
],
),
);
final user = PlatformUser.of(
id: 'user_0',
location: location,
);
await PlatformUserRepository.create(user);
final storedUser = await PlatformUserRepository.getAsync('user_0');
/// Should print 1 location
print('${storedUser?.location?.value?.query}\n');
runApp(myApp());
}
Further repositories #
I cannot go into all details here. Feel free to explore and to use further repositories:
PlatformMediaRepository
PlatformPostEntitiesRepository
FocusRepository
FocusMetricsRepository
MapBoxPlaceRepository
MapBoxPlaceContextRepository
As mentioned above you won't need any of these when you want to create new embedded objects like media, location or address. All of embedded objects will be created and persisted when its parent is created.
Since in this package PlatformPost
is the root of all model objects it is highly recommended to use PlatformPostRepository.create
to persist and to create all of embedded objects.
If you want to update an object please use create
function of corresponding repository.
In most cases you have the choice of async or sync GET or GET_ALL in each repository.
You also are able to use delete
function in each repository if you want to remove any of objects. You don't need to consider the parent object since the repository will care of indexes.
Further notes #
Feel free to add comments and improvements. I hope it will be fun for you to use this package and you will create your social media or link an existing social media with help of this package in a very quick way.
Future releases will include: #
- Tap on post in list will open fullscreen of the post
- Header with a menu and switch between 'users' and 'posts'
- Grid view to show all users
- Map view to show all users by their locations
- Switch between different types of users of your social media
- User preview as an overlay over the list/grid/map.
- Filter as an overlay over the list/grid/map.
- Filter users by age/distance/...
Future releases will replace this dependencies: #
- Currently, using Cached Video Player instead of Chewie Player to get web support
License #
Copyright 2022 Ilja Lichtenberg
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
End license text.