mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 13:33:32 +00:00
Merge branch 'main' into codemagic-setup
This commit is contained in:
commit
cbd6ac42b5
8 changed files with 179 additions and 47 deletions
38
CHANGELOG.md
38
CHANGELOG.md
|
@ -1,5 +1,43 @@
|
|||
# Relatica Change Log
|
||||
|
||||
## Version 0.8.0 (beta)
|
||||
|
||||
* Changes
|
||||
* "Groups" have been renamed "Circles" to match the upcoming Friendica release nomenclature change.
|
||||
* Timeline selector has now been merged into one big list with a divider between the standard types and the circles
|
||||
* User Profile screen buttons have been rearranged so that (un)block and (un)follow are on their own line
|
||||
* Notifications processing has been streamlined again, especially for older notifications
|
||||
* Contacts information is updated as the data comes in (may need to pull this out since it can temporarily show
|
||||
incorrect connection information before the followers mapping occurs)
|
||||
* Link preview has a new more efficient layout with the photo on top and the text caption underneath
|
||||
* Sign-in screen has been changed to be more user-friendly
|
||||
* Start-up splash screen has more prompts to let users know what is happening and timeouts when trying to
|
||||
communicate with the servers. If nothing is logged in it drops to the sign in screen rather than staying on splash
|
||||
screen.
|
||||
* Streamlined the visibility selection in the post/comment editor
|
||||
* Interactions toolbar has been streamlined. Navigating to the screen with details on who liked/reshared etc. is now
|
||||
in menu and clicking in any free space in the post card area (except around images/videos since that is
|
||||
technically part of a media carousel control).
|
||||
* When saving images on mobile it writes to the photo gallery than the files area.
|
||||
* Fixes
|
||||
* Adding/removing of users from Circles properly reflects on profile screen (before needed to navigate away and back
|
||||
to get it to appear)
|
||||
* Multiclicking on notifications will not cause multiple navigations to that post/comment
|
||||
* Multiclicking on post/comment creation will not cause multiple creation events
|
||||
* Loading newer notifications works.
|
||||
* Changing profiles when on the Contacts or Search screen now properly reflect the change
|
||||
* Fix privacy levels on response to Mastodon direct messages. Previously it would expand the privacy to include
|
||||
followers
|
||||
* Image/video size in post/comment viewer doesn't overflow the boundaries of the card
|
||||
* Unresharing a post doesn't cause it to disappear
|
||||
* Image viewer screen has better fill and image text appears after clicking ALT button rather than as a caption
|
||||
* Resharing of comments in Friendica is spotty through the UI and even more so through the API. It has been removed
|
||||
for the time being
|
||||
* PNG images always displayed very low res thumbnails that Friendica generates. PNGs now always load the full size
|
||||
image, for previews and full views
|
||||
* New Features
|
||||
* Can click on the visibility icon on posts to get a dialog box listing the visibility of the post/comment
|
||||
|
||||
## Version 0.7.2 (beta)
|
||||
|
||||
* Changes
|
||||
|
|
21
PRIVACY.md
Normal file
21
PRIVACY.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
Privacy Policy
|
||||
My Social Portal LLC (MSP) built the Relatica app as an Open Source app. This SERVICE is provided by MSP at no cost and is intended for use as is.
|
||||
|
||||
This page is used to inform visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.
|
||||
|
||||
If you choose to use our Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that we collect is used for providing and improving the Service. We will not use or share your information with anyone except as described in this Privacy Policy.
|
||||
|
||||
The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which are accessible at Kyanite unless otherwise defined in this Privacy Policy.
|
||||
|
||||
## Information Collection and Use
|
||||
We do not collect any information about the execution, usage of, or state of the Relatica application or any data that it interacts with or processes beyond what the various app stores implicitly track in terms of downloads, sessions, etc. that we have no control over.
|
||||
|
||||
## Changes to This Privacy Policy
|
||||
We may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page.
|
||||
|
||||
This policy is effective as of 2023-11-18
|
||||
|
||||
## Contact Us
|
||||
If you have any questions or suggestions about our Privacy Policy, do not hesitate to contact us at support@myportal.social.
|
||||
|
||||
This privacy policy page was created at privacypolicytemplate.net and modified/generated by App Privacy Policy Generator
|
|
@ -122,7 +122,13 @@ class _StatusControlState extends State<FlattenedTreeEntryControl> {
|
|||
top: otherPadding,
|
||||
bottom: otherPadding,
|
||||
),
|
||||
child: bodyCard,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (widget.showStatusOpenButton) {
|
||||
_goToPostView();
|
||||
}
|
||||
},
|
||||
child: bodyCard),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -265,6 +271,10 @@ class _StatusControlState extends State<FlattenedTreeEntryControl> {
|
|||
copyText,
|
||||
];
|
||||
|
||||
if (options.first == divider) {
|
||||
options.removeAt(0);
|
||||
}
|
||||
|
||||
final entry = widget.originalItem.timelineEntry;
|
||||
|
||||
return PopupMenuButton<String>(onSelected: (menuOption) async {
|
||||
|
@ -274,8 +284,7 @@ class _StatusControlState extends State<FlattenedTreeEntryControl> {
|
|||
|
||||
switch (menuOption) {
|
||||
case goToPost:
|
||||
context.push(
|
||||
'/post/view/${item.timelineEntry.id}/${item.timelineEntry.id}');
|
||||
_goToPostView();
|
||||
break;
|
||||
case editStatus:
|
||||
if (item.timelineEntry.parentId.isEmpty) {
|
||||
|
@ -361,4 +370,9 @@ class _StatusControlState extends State<FlattenedTreeEntryControl> {
|
|||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _goToPostView() {
|
||||
context
|
||||
.push('/post/view/${item.timelineEntry.id}/${item.timelineEntry.id}');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ class EntryTreeItem {
|
|||
_children.addAll(initialChildren ?? {});
|
||||
}
|
||||
|
||||
factory EntryTreeItem.empty() => EntryTreeItem(TimelineEntry());
|
||||
|
||||
EntryTreeItem copy({required TimelineEntry entry}) => EntryTreeItem(
|
||||
entry,
|
||||
isMine: isMine,
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:result_monad/result_monad.dart';
|
|||
|
||||
import '../friendica_client/friendica_client.dart';
|
||||
import '../friendica_client/paging_data.dart';
|
||||
import '../globals.dart';
|
||||
import '../models/TimelineIdentifiers.dart';
|
||||
import '../models/auth/profile.dart';
|
||||
import '../models/entry_tree_item.dart';
|
||||
|
@ -13,7 +14,9 @@ import '../models/image_entry.dart';
|
|||
import '../models/media_attachment_uploads/new_entry_media_items.dart';
|
||||
import '../models/timeline_entry.dart';
|
||||
import '../models/visibility.dart';
|
||||
import '../utils/active_profile_selector.dart';
|
||||
import 'media_upload_attachment_helper.dart';
|
||||
import 'reshared_via_service.dart';
|
||||
|
||||
class EntryManagerService extends ChangeNotifier {
|
||||
static final _logger = Logger('$EntryManagerService');
|
||||
|
@ -425,33 +428,55 @@ class EntryManagerService extends ChangeNotifier {
|
|||
|
||||
FutureResult<EntryTreeItem, ExecError> resharePost(String id) async {
|
||||
_logger.finest('Resharing post: $id');
|
||||
final resharedViaService = getIt<ActiveProfileSelector<ReshareViaService>>()
|
||||
.getForProfile(profile)
|
||||
.fold(
|
||||
onSuccess: (s) => s,
|
||||
onError: (error) {
|
||||
_logger.severe('Error getting reshared via service: $error');
|
||||
return null;
|
||||
});
|
||||
final client = StatusesClient(profile);
|
||||
final idForCall = id;
|
||||
final result =
|
||||
await client.resharePost(idForCall).andThenSuccessAsync((item) async {
|
||||
resharedViaService?.upsertResharedVia(postId: id, resharerId: profile.id);
|
||||
await processNewItems([item], client.profile.username, null);
|
||||
});
|
||||
|
||||
return result.mapValue((_) {
|
||||
_logger.finest('$id post updated after reshare');
|
||||
return _nodeToTreeItem(_postNodes[id]!, client.profile.userId);
|
||||
}).mapError(
|
||||
(error) {
|
||||
_logger.finest('$id error updating: $error');
|
||||
return ExecError(
|
||||
type: ErrorType.localError,
|
||||
message: error.toString(),
|
||||
return result
|
||||
.mapValue((_) {
|
||||
_logger.finest('$id post updated after reshare');
|
||||
return _nodeToTreeItem(_postNodes[id]!, client.profile.userId);
|
||||
})
|
||||
.withResult((_) => notifyListeners())
|
||||
.mapError(
|
||||
(error) {
|
||||
_logger.finest('$id error updating: $error');
|
||||
return ExecError(
|
||||
type: ErrorType.localError,
|
||||
message: error.toString(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
FutureResult<bool, ExecError> unResharePost(String id) async {
|
||||
FutureResult<EntryTreeItem, ExecError> unResharePost(String id) async {
|
||||
_logger.finest('Unresharing post: $id');
|
||||
final resharedViaService = getIt<ActiveProfileSelector<ReshareViaService>>()
|
||||
.getForProfile(profile)
|
||||
.fold(
|
||||
onSuccess: (s) => s,
|
||||
onError: (error) {
|
||||
_logger.severe('Error getting reshared via service: $error');
|
||||
return null;
|
||||
});
|
||||
final client = StatusesClient(profile);
|
||||
final idForCall = id;
|
||||
final result =
|
||||
await client.unResharePost(idForCall).andThenSuccessAsync((item) async {
|
||||
resharedViaService?.upsertRemovedSharer(
|
||||
postId: id, resharerId: profile.id);
|
||||
await processNewItems([item], client.profile.username, null);
|
||||
});
|
||||
|
||||
|
@ -459,10 +484,21 @@ class EntryManagerService extends ChangeNotifier {
|
|||
return Result.error(result.error);
|
||||
}
|
||||
|
||||
_cleanupEntriesForId(id);
|
||||
notifyListeners();
|
||||
|
||||
return Result.ok(true);
|
||||
return result
|
||||
.mapValue((_) {
|
||||
_logger.finest('$id post updated after reshare');
|
||||
return _nodeToTreeItem(_postNodes[id]!, client.profile.userId);
|
||||
})
|
||||
.withResult((_) => notifyListeners())
|
||||
.mapError(
|
||||
(error) {
|
||||
_logger.finest('$id error updating: $error');
|
||||
return ExecError(
|
||||
type: ErrorType.localError,
|
||||
message: error.toString(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
FutureResult<EntryTreeItem, ExecError> toggleFavorited(
|
||||
|
|
|
@ -11,6 +11,16 @@ class ReshareViaService {
|
|||
|
||||
_postsVia[postId] = resharedData.withUpsertedResharer(resharerId);
|
||||
}
|
||||
|
||||
void upsertRemovedSharer(
|
||||
{required String postId, required String resharerId}) {
|
||||
final resharedData = _postsVia.putIfAbsent(
|
||||
postId,
|
||||
() => ResharedViaData(postId: postId),
|
||||
);
|
||||
|
||||
_postsVia[postId] = resharedData.withRemovedResharer(resharerId);
|
||||
}
|
||||
}
|
||||
|
||||
class ResharedViaData {
|
||||
|
@ -28,4 +38,9 @@ class ResharedViaData {
|
|||
postId: postId,
|
||||
resharers: {resharerId, ...resharers},
|
||||
);
|
||||
|
||||
ResharedViaData withRemovedResharer(String resharerId) => ResharedViaData(
|
||||
postId: postId,
|
||||
resharers: resharers..remove(resharerId),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -154,15 +154,29 @@ class TimelineManager extends ChangeNotifier {
|
|||
|
||||
FutureResult<EntryTreeItem, ExecError> resharePost(String id) async {
|
||||
final result = await entryManagerService.resharePost(id);
|
||||
final empty = EntryTreeItem.empty();
|
||||
if (result.isSuccess) {
|
||||
for (final t in cachedTimelines.values) {
|
||||
if (t.posts.firstWhere((p) => p.id == id, orElse: () => empty) !=
|
||||
empty) {
|
||||
t.addOrUpdate([result.value]);
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FutureResult<bool, ExecError> unResharePost(String id) async {
|
||||
FutureResult<EntryTreeItem, ExecError> unResharePost(String id) async {
|
||||
final result = await entryManagerService.unResharePost(id);
|
||||
final empty = EntryTreeItem.empty();
|
||||
if (result.isSuccess) {
|
||||
for (final t in cachedTimelines.values) {
|
||||
if (t.posts.firstWhere((p) => p.id == id, orElse: () => empty) !=
|
||||
empty) {
|
||||
t.addOrUpdate([result.value]);
|
||||
}
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
return result;
|
||||
|
|
46
pubspec.lock
46
pubspec.lock
|
@ -181,10 +181,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
version: "1.17.1"
|
||||
color_blindness:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -705,10 +705,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
version: "0.18.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -761,18 +761,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
version: "0.12.15"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "0.2.0"
|
||||
media_kit:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -849,10 +849,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.9.1"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1239,10 +1239,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.9.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1279,18 +1279,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
version: "1.11.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
version: "2.1.1"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1335,10 +1335,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.5.1"
|
||||
time_machine:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1555,14 +1555,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1620,5 +1612,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
|
|
Loading…
Reference in a new issue