Skip to content

Commit

Permalink
bfix(favorites): changed state of starred is not reflected when moved…
Browse files Browse the repository at this point in the history
… to previous screen
  • Loading branch information
aman-singh7 committed Feb 3, 2022
1 parent 99793de commit add1f2a
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 79 deletions.
48 changes: 46 additions & 2 deletions lib/models/projects.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ class Project {
ProjectRelationships relationships;
List<Collaborator>? collaborators;

Project copyWith({
String? id,
String? type,
ProjectAttributes? attributes,
ProjectRelationships? relationships,
List<Collaborator>? collaborators,
}) {
return Project(
id: id ?? this.id,
type: type ?? this.type,
attributes: attributes ?? this.attributes,
relationships: relationships ?? this.relationships,
collaborators: collaborators ?? this.collaborators,
);
}

bool get hasAuthorAccess {
var currentUser = locator<LocalStorageService>().currentUser;

Expand Down Expand Up @@ -81,7 +97,7 @@ class ProjectAttributes {
this.description,
required this.view,
required this.tags,
this.isStarred,
required this.isStarred,
required this.authorName,
required this.starsCount,
});
Expand All @@ -94,9 +110,37 @@ class ProjectAttributes {
String? description;
int view;
List<Tag> tags;
bool? isStarred;
bool isStarred;
String authorName;
int starsCount;

ProjectAttributes copyWith({
String? name,
String? projectAccessType,
DateTime? createdAt,
DateTime? updatedAt,
ImagePreview? imagePreview,
String? description,
int? view,
List<Tag>? tags,
bool? isStarred,
String? authorName,
int? starsCount,
}) {
return ProjectAttributes(
name: name ?? this.name,
projectAccessType: projectAccessType ?? this.projectAccessType,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
imagePreview: imagePreview ?? this.imagePreview,
view: view ?? this.view,
tags: tags ?? this.tags,
authorName: authorName ?? this.authorName,
starsCount: starsCount ?? this.starsCount,
description: description ?? this.description,
isStarred: isStarred ?? this.isStarred,
);
}
}

class ImagePreview {
Expand Down
1 change: 1 addition & 0 deletions lib/ui/views/profile/user_favourites_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class _UserFavouritesViewState extends State<UserFavouritesView>
var _result = await Get.toNamed(ProjectDetailsView.id,
arguments: project);
if (_result is bool) model.onProjectDeleted(project.id);
if (_result is Project) model.onProjectUnstarred(project.id);
},
),
);
Expand Down
10 changes: 9 additions & 1 deletion lib/ui/views/projects/featured_projects_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mobile_app/models/projects.dart';
import 'package:mobile_app/ui/components/cv_header.dart';
import 'package:mobile_app/ui/components/cv_primary_button.dart';
import 'package:mobile_app/ui/views/base_view.dart';
Expand Down Expand Up @@ -38,7 +39,14 @@ class _FeaturedProjectsViewState extends State<FeaturedProjectsView> {
FeaturedProjectCard(
project: project,
onViewPressed: () async {
await Get.toNamed(ProjectDetailsView.id, arguments: project);
final _result = await Get.toNamed(
ProjectDetailsView.id,
arguments: project,
);

if (_result is Project) {
model.updateFeaturedProject(_result);
}
},
),
);
Expand Down
160 changes: 85 additions & 75 deletions lib/ui/views/projects/project_details_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import 'package:mobile_app/locator.dart';
import 'package:mobile_app/models/collaborators.dart';
import 'package:mobile_app/models/projects.dart';
import 'package:mobile_app/services/dialog_service.dart';
import 'package:mobile_app/services/local_storage_service.dart';
import 'package:mobile_app/ui/components/cv_flat_button.dart';
import 'package:mobile_app/ui/views/base_view.dart';
import 'package:mobile_app/ui/views/profile/profile_view.dart';
Expand All @@ -32,8 +31,6 @@ class ProjectDetailsView extends StatefulWidget {
}

class _ProjectDetailsViewState extends State<ProjectDetailsView> {
final LocalStorageService _localStorageService =
locator<LocalStorageService>();
final DialogService _dialogService = locator<DialogService>();
late ProjectDetailsViewModel _model;
final _formKey = GlobalKey<FormState>();
Expand Down Expand Up @@ -566,92 +563,105 @@ class _ProjectDetailsViewState extends State<ProjectDetailsView> {
return BaseView<ProjectDetailsViewModel>(
onModelReady: (model) {
_model = model;
_model.receivedProject = _recievedProject;
// initialize collaborators & isStarred for the project..
_model.collaborators = _recievedProject.collaborators;
_model.isProjectStarred =
_recievedProject.attributes.isStarred ?? false;
_model.isProjectStarred = _recievedProject.attributes.isStarred;
_model.starCount = _recievedProject.attributes.starsCount;

_model.fetchProjectDetails(_recievedProject.id);
},
builder: (context, model, child) => Scaffold(
appBar: AppBar(
title: const Text('Project Details'),
actions: [
_buildShareActionButton(),
],
),
body: Builder(builder: (context) {
var _projectAttrs = _recievedProject.attributes;
var _items = <Widget>[];

// Adds project preview..
_items.add(_buildProjectPreview());

_items.add(const SizedBox(height: 16));

// Adds Project Name, Star & View count..
_items.add(_buildProjectNameHeader());

// Adds Project attributes..
_items.add(
Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildProjectAuthor(),
_buildProjectDetailComponent(
'Project Access Type',
_projectAttrs.projectAccessType,
),
_buildProjectDescription(),
const Divider(height: 32),
Wrap(
spacing: 8,
crossAxisAlignment: WrapCrossAlignment.center,
builder: (context, model, child) => WillPopScope(
onWillPop: () async {
// Check whether the state (i.e starred or not) is changed
final bool isChanged = model.receivedProject.attributes.isStarred ^
_recievedProject.attributes.isStarred;
Get.back(
result: isChanged ? model.receivedProject : null,
);
return false;
},
child: Scaffold(
appBar: AppBar(
title: const Text('Project Details'),
actions: [
_buildShareActionButton(),
],
),
body: Builder(
builder: (context) {
var _projectAttrs = _recievedProject.attributes;
var _items = <Widget>[];

// Adds project preview..
_items.add(_buildProjectPreview());

_items.add(const SizedBox(height: 16));

// Adds Project Name, Star & View count..
_items.add(_buildProjectNameHeader());

// Adds Project attributes..
_items.add(
Container(
padding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (!_recievedProject.hasAuthorAccess &&
_localStorageService.isLoggedIn)
_buildForkProjectButton(),
if (_localStorageService.isLoggedIn)
_buildStarProjectButton(),
_buildProjectAuthor(),
_buildProjectDetailComponent(
'Project Access Type',
_projectAttrs.projectAccessType,
),
_buildProjectDescription(),
const Divider(height: 32),
Wrap(
spacing: 8,
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
if (!_recievedProject.hasAuthorAccess &&
model.isLoggedIn)
_buildForkProjectButton(),
if (model.isLoggedIn) _buildStarProjectButton(),
if (_recievedProject.hasAuthorAccess)
_buildAddCollaboratorsButton(),
],
),
const Divider(height: 32),
if (_recievedProject.hasAuthorAccess)
_buildAddCollaboratorsButton(),
Wrap(
spacing: 8,
children: <Widget>[
_buildEditButton(),
_buildDeleteButton(),
],
),
],
),
const Divider(height: 32),
if (_recievedProject.hasAuthorAccess)
Wrap(
spacing: 8,
children: <Widget>[
_buildEditButton(),
_buildDeleteButton(),
],
),
],
),
),
);
),
);

if (_model.isSuccess(_model.FETCH_PROJECT_DETAILS) &&
_model.collaborators.isNotEmpty) {
_items.add(const Divider());
if (_model.isSuccess(_model.FETCH_PROJECT_DETAILS) &&
_model.collaborators.isNotEmpty) {
_items.add(const Divider());

_items.add(_buildProjectHeader('Collaborators'));
_items.add(_buildProjectHeader('Collaborators'));

for (var collaborator in _model.collaborators) {
_items.add(
_buildCollaborator(collaborator),
for (var collaborator in _model.collaborators) {
_items.add(
_buildCollaborator(collaborator),
);
}
}
return ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(16),
children: _items,
);
}
}
return ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(16),
children: _items,
);
}),
},
),
),
),
);
}
Expand Down
10 changes: 9 additions & 1 deletion lib/viewmodels/profile/user_favourites_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,19 @@ class UserFavouritesViewModel extends BaseModel {
notifyListeners();
}

void onProjectDeleted(String projectId) {
void _removeFromUserFavorites(String projectId) {
_userFavourites.removeWhere((_project) => _project.id == projectId);
notifyListeners();
}

void onProjectDeleted(String projectId) {
_removeFromUserFavorites(projectId);
}

void onProjectUnstarred(String projectId) {
_removeFromUserFavorites(projectId);
}

Future? fetchUserFavourites({String? userId}) async {
try {
if (previousUserFavouritesBatch?.links.next != null) {
Expand Down
8 changes: 8 additions & 0 deletions lib/viewmodels/projects/featured_projects_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ class FeaturedProjectsViewModel extends BaseModel {
notifyListeners();
}

void updateFeaturedProject(Project project) {
final int index = _featuredProjects.indexWhere(
(element) => element.id == project.id,
);
_featuredProjects[index] = project;
notifyListeners();
}

Future? fetchFeaturedProjects({int size = 5}) async {
try {
if (previousFeaturedProjectsBatch?.links.next != null) {
Expand Down
14 changes: 14 additions & 0 deletions lib/viewmodels/projects/project_details_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:mobile_app/models/failure_model.dart';
import 'package:mobile_app/models/projects.dart';
import 'package:mobile_app/services/API/collaborators_api.dart';
import 'package:mobile_app/services/API/projects_api.dart';
import 'package:mobile_app/services/local_storage_service.dart';
import 'package:mobile_app/viewmodels/base_viewmodel.dart';

class ProjectDetailsViewModel extends BaseModel {
Expand All @@ -18,6 +19,12 @@ class ProjectDetailsViewModel extends BaseModel {

final ProjectsApi _projectsApi = locator<ProjectsApi>();
final CollaboratorsApi _collaboratorsApi = locator<CollaboratorsApi>();
final LocalStorageService _localStorageService =
locator<LocalStorageService>();

bool get isLoggedIn => _localStorageService.isLoggedIn;

late Project receivedProject;

Project? _project;

Expand Down Expand Up @@ -164,6 +171,13 @@ class ProjectDetailsViewModel extends BaseModel {
isProjectStarred = _toggleMessage!.contains('Starred') ? true : false;
isProjectStarred ? starCount++ : starCount--;

receivedProject = receivedProject.copyWith(
attributes: receivedProject.attributes.copyWith(
isStarred: isProjectStarred,
starsCount: starCount,
),
);

setStateFor(TOGGLE_STAR, ViewState.Success);
} on Failure catch (f) {
setStateFor(TOGGLE_STAR, ViewState.Error);
Expand Down

0 comments on commit add1f2a

Please sign in to comment.