Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

✨ Confirm dialog when opening URLs #373

Open
wants to merge 27 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7cab142
:construction: Added a proof-of-concept bottom sheet on url tapped
Komposten Aug 21, 2019
ddd06f7
:bug: Wrap url in ScrollView to handle long urls in confirm open dialog
Komposten Aug 21, 2019
cc6f7ad
:sparkles: Implement "don't ask again" for url dialog
Komposten Aug 21, 2019
72c5251
:sparkles: Add "don't ask for host" for url dialog
Komposten Aug 22, 2019
4a0ead9
:lipstick: Update design of "don't ask for host" in url dialog
Komposten Aug 22, 2019
81191a2
:recycle: Move trusted URLs storage to user preferences
Komposten Aug 25, 2019
ccbe521
:bug: Fix dismissing open url dialog saving checkbox states
Komposten Aug 25, 2019
104a47a
:bug: Uncheck and disable "trust domain" when "never ask" is checked
Komposten Aug 25, 2019
4f303db
:sparkles: Add link confirmation to all user-defined links
Komposten Aug 25, 2019
284c516
:recycle: Save the trusted domains as a list instead of string
Komposten Aug 25, 2019
a2f4d29
:sparkles: Add a settings page for trusted URLs
Komposten Aug 25, 2019
e03b545
:sparkles: Root domain detection for the open url dialog
Komposten Aug 27, 2019
29e96f8
:lipstick: Add a separator to application settings
Komposten Aug 27, 2019
7b69ed3
:globe_with_meridians: Update clear app prefs text
Komposten Aug 27, 2019
5fe5cb1
:bug: Fix trusted domains not loading if empty list
Komposten Aug 28, 2019
7b1df56
:globe_with_meridians: Update localisation files
Komposten Sep 2, 2019
5050746
:page_facing_up: Add the public suffix list to LICENSE-3RD-PARTY
Komposten Sep 2, 2019
594adaf
:fire: Remove unused variables
Komposten Sep 2, 2019
05d1f1f
:ok_hand: Confirm url dialog toggles now behave like radio buttons
Komposten Sep 7, 2019
ff6d409
:ok_hand: Logout clears trusted domains and "never ask"
Komposten Sep 8, 2019
ae60a49
:ok_hand: Update "Clear app preferences" description
Komposten Sep 8, 2019
93d5eb0
:globe_with_meridians: Move app settings localisation to application_…
Komposten Sep 8, 2019
75dee5b
Merge branch 'develop' into feature/confirm-open-url
Komposten Oct 4, 2019
fa0387c
:fire: Clean up after merging develop
Komposten Oct 7, 2019
102051e
:sparkles: Add "no items" widgets and refresh indicator to trusted do…
Komposten Oct 7, 2019
674b01b
:ok_hand: Use slidable for delete action in trusted domains list
Komposten Oct 8, 2019
3f8681e
Merge branch 'develop' into feature/confirm-open-url
Komposten Oct 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions LICENSE-3RD-PARTY
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
Applies to: The Public Suffix List (assets/other/public_suffix_list.dat)

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. You can obtain a copy of this license from
https://mozilla.org/MPL/2.0/.
-----------------------------------------------------------------------------
53 changes: 53 additions & 0 deletions assets/i18n/en/application_settings.arb
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,58 @@
"@comment_sort_oldest_first": {
"type": "text",
"placeholders": {}
},
"trusted_domains_title": "Manage trusted domains",
"@trusted_domains_title": {
"description": "Title for the Trusted Domains settings page.",
"type": "text",
"placeholders": {}
},
"ask_for_urls": "Link confirmation",
"@ask_for_urls": {
"description": "Header for the \"ask to open URLs\" and \"trusted domains\" settings.",
"type": "text",
"placeholders": {}
},
"ask_for_urls_setting": "Ask to open links",
"@ask_for_urls_setting": {
"type": "text",
"placeholders": {}
},
"trusted_domains_text": "Trusted domains",
"@trusted_domains_text": {
"description": "Text on the button to the Trusted Domains settings page.",
"type": "text",
"placeholders": {}
},
"trusted_domains_desc": "Manage web domains you have marked as trusted.",
"@trusted_domains_desc": {
"type": "text",
"placeholders": {}
},
"trusted_domains_resource": "trusted domains",
"@trusted_domains_resource": {
"type": "text",
"placeholders": {}
},
"delete_domain_failure": "Could not delete the trusted domain",
"@delete_domain_failure": {
"type": "text",
"placeholders": {}
},
"confirm_url_enabled": "Only untrusted",
"@confirm_url_enabled": {
"type": "text",
"placeholders": {}
},
"confirm_url_disabled": "Never",
"@confirm_url_disabled": {
"type": "text",
"placeholders": {}
},
"delete_domain": "Delete",
"@delete_domain": {
"type": "text",
"placeholders": {}
}
}
25 changes: 25 additions & 0 deletions assets/i18n/en/post.arb
Original file line number Diff line number Diff line change
Expand Up @@ -607,5 +607,30 @@
"description": "Shown when a post was immediately posted, as in time posted is 'now'.Should be as few characters as possible.",
"type": "text",
"placeholders": {}
},
"open_url_message": "Do you want to open this link in your browser?",
"@open_url_message": {
"type": "text",
"placeholders": {}
},
"open_url_continue": "Continue",
"@open_url_continue": {
"type": "text",
"placeholders": {}
},
"open_url_cancel": "Cancel",
"@open_url_cancel": {
"type": "text",
"placeholders": {}
},
"open_url_dont_ask_again": "Never ask again",
"@open_url_dont_ask_again": {
"type": "text",
"placeholders": {}
},
"open_url_dont_ask_again_for": "Trust this domain",
"@open_url_dont_ask_again_for": {
"type": "text",
"placeholders": {}
}
}
2 changes: 1 addition & 1 deletion assets/i18n/en/user.arb
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@
"type": "text",
"placeholders": {}
},
"clear_app_preferences_desc": "Clear the application preferences. Currently this is only the preferred order of comments.",
"clear_app_preferences_desc": "Clear the application preferences. Currently only the preferred order of comments and the list of trusted domains.",
"@clear_app_preferences_desc": {
Komposten marked this conversation as resolved.
Show resolved Hide resolved
"type": "text",
"placeholders": {}
Expand Down
1 change: 1 addition & 0 deletions lib/pages/auth/create_account/guidelines_step.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class OBAuthGuidelinesStepPageState extends State<OBAuthGuidelinesStepPage> {
)
: OBMarkdown(
onlyBody: true,
linksRequireConfirmation: false,
data: _communityGuidelines,
theme: OBTheme(
primaryTextColor: '#ffffff',
Expand Down
169 changes: 169 additions & 0 deletions lib/pages/home/bottom_sheets/confirm_open_url.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import 'package:Okuna/models/theme.dart';
import 'package:Okuna/provider.dart';
import 'package:Okuna/services/localization.dart';
import 'package:Okuna/services/theme.dart';
import 'package:Okuna/services/theme_value_parser.dart';
import 'package:Okuna/services/user_preferences.dart';
import 'package:Okuna/widgets/buttons/button.dart';
import 'package:Okuna/widgets/fields/checkbox_field.dart';
import 'package:Okuna/widgets/theming/primary_color_container.dart';
import 'package:Okuna/widgets/theming/smart_text.dart';
import 'package:flutter/material.dart';
import 'package:public_suffix/public_suffix.dart';

class OBConfirmOpenUrlBottomSheet extends StatefulWidget {
final PublicSuffix _urlInfo;

OBConfirmOpenUrlBottomSheet({PublicSuffix urlInfo}) : _urlInfo = urlInfo;

@override
OBConfirmOpenUrlBottomSheetState createState() {
return OBConfirmOpenUrlBottomSheetState();
}
}

class OBConfirmOpenUrlBottomSheetState extends State<OBConfirmOpenUrlBottomSheet> {
UserPreferencesService _preferencesService;
LocalizationService _localizationService;
ThemeService _themeService;
ThemeValueParserService _themeValueParserService;

bool _needsBootstrap;
bool _ask;
bool _askForHost;


@override
void initState() {
super.initState();
_needsBootstrap = true;
_ask = true;
_askForHost = true;
}


@override
Widget build(BuildContext context) {
if (_needsBootstrap) {
var openbookProvider = OpenbookProvider.of(context);
_preferencesService = openbookProvider.userPreferencesService;
_localizationService = openbookProvider.localizationService;
_themeService = openbookProvider.themeService;
_themeValueParserService = openbookProvider.themeValueParserService;
_needsBootstrap = false;
}

double screenHeight = MediaQuery.of(context).size.height;
double maxUrlBoxHeight = screenHeight * .3;

OBTheme theme = _themeService.getActiveTheme();
Color secondaryTextColor = _themeValueParserService.parseColor(theme.secondaryTextColor);

return OBPrimaryColorContainer(
mainAxisSize: MainAxisSize.min,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
OBText(
_localizationService.post__open_url_message,
textAlign: TextAlign.start,
),
const SizedBox(
height: 10,
),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: maxUrlBoxHeight),
child: SingleChildScrollView(
child: OBSmartText(
text: widget._urlInfo.sourceUri.toString(),
),
),
),
const SizedBox(
height: 10,
),
OBCheckboxField(
value: !_askForHost,
onTap: _toggleDontAskForHost,
title: _localizationService.post__open_url_dont_ask_again_for,
titleStyle: TextStyle(fontWeight: FontWeight.normal),
subtitle: widget._urlInfo.domain,
subtitleStyle: TextStyle(color: secondaryTextColor),
),
const SizedBox(
height: 5,
),
OBCheckboxField(
value: !_ask,
title: _localizationService.post__open_url_dont_ask_again,
onTap: _toggleDontAsk,
titleStyle: TextStyle(fontWeight: FontWeight.normal),
),
const SizedBox(
height: 10,
),
Row(
children: <Widget>[
Expanded(
child: OBButton(
size: OBButtonSize.medium,
type: OBButtonType.highlight,
child: Text(_localizationService.post__open_url_cancel),
onPressed: _onCancel,
),
),
const SizedBox(
width: 20,
),
Expanded(
child: OBButton(
size: OBButtonSize.medium,
type: OBButtonType.primary,
child: Text(_localizationService.post__open_url_continue),
onPressed: _onConfirmTapped,
),
),
],
),
],
),
),
);
}

void _toggleDontAskForHost() {
setState(() {
_askForHost = !_askForHost;
_ask = true;
});
}

void _toggleDontAsk() {
setState(() {
_ask = !_ask;
_askForHost = true;
});
}

void _onConfirmTapped() async {
if (!_askForHost) {
await _preferencesService.setAskToConfirmOpenUrl(
_askForHost, host: widget._urlInfo);
}
if (!_ask) {
await _preferencesService.setAskToConfirmOpenUrl(_ask);
}

_onConfirmOpen();
}

void _onConfirmOpen() {
Navigator.pop(context, true);
}

void _onCancel() {
Navigator.pop(context, false);
}
}
63 changes: 63 additions & 0 deletions lib/pages/home/bottom_sheets/confirm_url_setting_picker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import 'package:Okuna/provider.dart';
import 'package:Okuna/widgets/theming/primary_color_container.dart';
import 'package:Okuna/widgets/theming/text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class OBConfirmUrlSettingPickerBottomSheet extends StatefulWidget {
final ValueChanged<bool> onTypeChanged;

final bool initialValue;

const OBConfirmUrlSettingPickerBottomSheet(
{Key key, @required this.onTypeChanged, this.initialValue})
: super(key: key);

@override
OBConfirmUrlSettingPickerBottomSheetState createState() {
return OBConfirmUrlSettingPickerBottomSheetState();
}
}

class OBConfirmUrlSettingPickerBottomSheetState
extends State<OBConfirmUrlSettingPickerBottomSheet> {
FixedExtentScrollController _cupertinoPickerController;
List<bool> allValues;

@override
void initState() {
super.initState();
allValues = [true, false];
_cupertinoPickerController = FixedExtentScrollController(
initialItem: widget.initialValue != null
? allValues.indexOf(widget.initialValue)
: 0,
);
}

@override
Widget build(BuildContext context) {
var openbookProvider = OpenbookProvider.of(context);

Map<bool, String> localizationMap = openbookProvider.userPreferencesService
.getConfirmUrlSettingLocalizationMap();

return OBPrimaryColorContainer(
mainAxisSize: MainAxisSize.min,
child: SizedBox(
height: 216,
child: CupertinoPicker(
scrollController: _cupertinoPickerController,
backgroundColor: Colors.transparent,
onSelectedItemChanged: (int index) {
widget.onTypeChanged(allValues[index]);
},
itemExtent: 32,
children: allValues.map((setting) {
return OBText(localizationMap[setting]);
}).toList(),
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class OBAcceptGuidelinesModalState extends State {
)
: OBMarkdown(
onlyBody: true,
linksRequireConfirmation: false,
data: _guidelinesText,
)
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class OBConfirmRejectGuidelinesState extends State<OBConfirmRejectGuidelines> {
subtitle: OBSecondaryText(
localizationService.user__confirm_guidelines_reject_join_slack),
onTap: () {
openbookProvider.urlLauncherService.launchUrl(
openbookProvider.urlLauncherService.launchUrlWithoutConfirmation(
'https://join.slack.com/t/okuna/shared_invite/enQtNDI2NjI3MDM0MzA2LTYwM2E1Y2NhYWRmNTMzZjFhYWZlYmM2YTQ0MWEwYjYyMzcxMGI0MTFhNTIwYjU2ZDI1YjllYzlhOWZjZDc4ZWY');
},
),
Expand Down
1 change: 1 addition & 0 deletions lib/pages/home/pages/menu/pages/community_guidelines.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class OBCommunityGuidelinesPageState extends State {
children: <Widget>[
Expanded(
child: OBMarkdown(
linksRequireConfirmation: false,
data: _guidelinesText,
)),
],
Expand Down
Loading