Skip to content

Commit

Permalink
Merge pull request #38 from fonkamloic/feat-screenshot-steam-test
Browse files Browse the repository at this point in the history
test: 100% Test coverage
  • Loading branch information
fonkamloic authored Jul 20, 2024
2 parents b3a9e7e + 1bdda7d commit 0fda76f
Show file tree
Hide file tree
Showing 14 changed files with 454 additions and 69 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ jobs:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1
with:
flutter_channel: stable
flutter_version: 3.3.7
flutter_version: 3.22.3
min_coverage: 75
exclude: "lib/no_screenshot_platform_interface.dart lib/no_screenshot_method_channel.dart"
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,16 @@ Updated readme and added sample usage.
- Upgrade android to support AGP 8.X
- merged fix by @alberto-cappellina PR[https://github.com/FlutterPlaza/no_screenshot/pull/27]
- gradle:7.1.2 -> 7.4.2
- kotlin_version = '1.6.10' -> '1.6.21'
- kotlin_version = '1.6.10' -> '1.6.21'


## 0.2.1

### Summary of Changes

- **Automatic State Persistence**: Removed the need to track `didChangeAppLifecycleState`. The state will now be automatically persisted using native platform SharedPreferences.
- **Enhanced Example**: Updated the example app to demonstrate the new automatic state persistence and usage of the `NoScreenshot` plugin.
- **Stream Support**: Provided a stream to listen for screenshot activities, making it easier to react to screenshots in real-time.
- **Bug Fixes**: Fixed various bugs related to screenshot detection and state management on both Android and iOS platforms.
- **Documentation Updates**: Improved documentation to reflect the new features and provide clearer usage examples.
- **Deprecation Notice**: Deprecated the use of the constructor `NoScreenshot()` in favor of the singleton `NoScreenshot.instance`.
4 changes: 3 additions & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Contributors

- [Felix Junghans](https://github.com/felixjunghans) - Freelance software developer from the Stuttgart area. [Bio](http://felixjunghans.de/)
- [Geoffrey Giordano](https://github.com/ggiordan) [PR](https://github.com/FlutterPlaza/no_screenshot/pull/29)
- [Musaddiq Ahmed Khan](https://github.com/Musaddiq625) [PR](https://github.com/FlutterPlaza/no_screenshot/pull/26)
- [alberto-cappellina](https://github.com/alberto-cappellina) [PR](https://github.com/FlutterPlaza/no_screenshot/pull/27)
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# no_screenshot

<p align="center">
<a href="https://pub.dev/packages/no_screenshot"><img src="https://img.shields.io/pub/v/no_screenshot.svg" alt="Pub"></a>
<a href="https://github.com/FlutterPlaza/no_screenshot/actions"><img src="https://github.com/FlutterPlaza/no_screenshot/workflows/build/badge.svg" alt="build"></a>
<a href="https://github.com/FlutterPlaza/no_screenshot"><img src="https://codecov.io/gh/FlutterPlaza/no_screenshot/branch/development/graph/badge.svg" alt="codecov"></a>
<a href="https://github.com/FlutterPlaza/no_screenshot"><img src="https://img.shields.io/github/stars/FlutterPlaza/no_screenshot.svg?style=flat&logo=github&colorB=deeppink&label=stars" alt="Star on Github"></a>
<a href="https://flutter.dev/docs/development/data-and-backend/state-mgmt/options#bloc--rx"><img src="https://img.shields.io/badge/flutter-website-deepskyblue.svg" alt="Flutter Website"></a>
</p>

Flutter plugin to enable, disable or toggle screenshot support in your application.

## Features
Expand All @@ -16,7 +24,7 @@ If you want to prevent user from taking screenshot or recording of your app. You
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
final _noScreenshot = NoScreenshot.instance;
AppLifecycleState? _notification;
AppLifecycleState? _notification;
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
case AppLifecycleState.resumed, :
Expand Down
123 changes: 91 additions & 32 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
# no_screenshot_example
# no_screenshot

Demonstrates how to use the no_screenshot plugin.
The Flutter plugin will enable, disable, or toggle screenshot support in your application.

## Getting Started
## Features

- Disables screenshot and screen recording on Android and iOS.
- Enables screenshot and screen recording on Android and iOS.
- Toggles screenshot and screen recording on Android and iOS.
- Provides a stream to listen for screenshot activities.

## Update

Tracking `didChangeAppLifecycleState` is no longer required. The state will be persisted automatically in the native platform SharedPreferences.

## Getting started

Add `no_screenshot` to your `pubspec.yaml` dependencies.

## Usage

Call the singleton `NoScreenshot.instance` anywhere you want to use it. For instance:

```dart
import 'package:flutter/material.dart';
import 'package:no_screenshot/no_screenshot.dart';
import 'package:no_screenshot/screenshot_snapshot.dart';
void main() {
runApp(const MyApp());
Expand All @@ -20,50 +38,91 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> {
final _noScreenshotPlugin = NoScreenshot();
final _noScreenshot = NoScreenshot.instance;
bool _isListeningToScreenshotSnapshot = false;
ScreenshotSnapshot _latestValue = ScreenshotSnapshot(
isScreenshotProtectionOn: false,
wasScreenshotTaken: false,
/// Returning screenshot path is not yet fully supported. And not function on iOS
screenshotPath: '',
);
@override
void initState() {
super.initState();
_noScreenshot.screenshotStream.listen((value) {
setState(() {
_latestValue = value;
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
title: const Text('No Screenshot Plugin Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
child: const Text('Press to toggle screenshot'),
onPressed: () async {
final result = await _noScreenshotPlugin.toggleScreenshot();
print(result);
},
),
ElevatedButton(
child: const Text('Press to turn off screenshot'),
onPressed: () async {
final result = await _noScreenshotPlugin.screenshotOff();
print(result);
},
),
ElevatedButton(
child: const Text('Press to turn on screenshot'),
onPressed: () async {
final result = await _noScreenshotPlugin.screenshotOn();
print(result);
},
),
],
)),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ElevatedButton(
onPressed: () async {
await _noScreenshot.startScreenshotListening();
setState(() {
_isListeningToScreenshotSnapshot = true;
});
},
child: const Text('Start Listening'),
),
ElevatedButton(
onPressed: () async {
await _noScreenshot.stopScreenshotListening();
setState(() {
_isListeningToScreenshotSnapshot = false;
});
},
child: const Text('Stop Listening'),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
"Screenshot Streaming is ${_isListeningToScreenshotSnapshot ? 'ON' : 'OFF'}\n\nIsScreenshotProtectionOn: ${_latestValue.isScreenshotProtectionOn}\nwasScreenshotTaken: ${_latestValue.wasScreenshotTaken}"),
),
ElevatedButton(
onPressed: () async {
bool result = await _noScreenshot.screenshotOff();
debugPrint('Screenshot Off: $result');
},
child: const Text('Disable Screenshot'),
),
ElevatedButton(
onPressed: () async {
bool result = await _noScreenshot.screenshotOn();
debugPrint('Enable Screenshot: $result');
},
child: const Text('Enable Screenshot'),
),
ElevatedButton(
onPressed: () async {
bool result = await _noScreenshot.toggleScreenshot();
debugPrint('Toggle Screenshot: $result');
},
child: const Text('Toggle Screenshot'),
),
const SizedBox(height: 20),
],
),
),
),
);
}
}
```

## Additional information

Check out our repo for Open-Source contributions. Contributions are welcome!
12 changes: 6 additions & 6 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
version: "4.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
Expand Down Expand Up @@ -103,10 +103,10 @@ packages:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "4.0.0"
matcher:
dependency: transitive
description:
Expand Down Expand Up @@ -137,7 +137,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.2.0"
version: "0.2.1"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -224,5 +224,5 @@ packages:
source: hosted
version: "14.2.1"
sdks:
dart: ">=3.3.0 <4.0.0"
dart: ">=3.4.4 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
6 changes: 3 additions & 3 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Demonstrates how to use the no_screenshot plugin.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.4.4 <4.0.0'

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
Expand All @@ -28,7 +28,7 @@ dependencies:

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
cupertino_icons: ^1.0.8

dev_dependencies:
flutter_test:
Expand All @@ -39,7 +39,7 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
flutter_lints: ^4.0.0

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
Expand Down
38 changes: 30 additions & 8 deletions lib/no_screenshot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'package:no_screenshot/screenshot_snapshot.dart';

import 'no_screenshot_platform_interface.dart';

/// A class that provides a platform-agnostic way to disable screenshots.
///
class NoScreenshot implements NoScreenshotPlatform {
final _instancePlatform = NoScreenshotPlatform.instance;
NoScreenshot._();
Expand All @@ -10,43 +12,63 @@ class NoScreenshot implements NoScreenshotPlatform {
"Using this may cause issue\nUse instance directly\ne.g: 'NoScreenshot.instance.screenshotOff()'")
NoScreenshot();

/// Made `NoScreenshot` class a singleton
static NoScreenshot get instance => NoScreenshot._();

/// Return `true` if screenshot capabilities has been successfully disabled
/// or is currently disabled and `false` otherwise. throw `UnmimplementedError` if not implement
/// Return `true` if screenshot capabilities has been
/// successfully disabled or is currently disabled and `false` otherwise.
/// throw `UnmimplementedError` if not implement
///
@override
Future<bool> screenshotOff() {
return _instancePlatform.screenshotOff();
}

/// Return `true` if screenshot capabilities has been successfully enable
/// or is currently enable and `false` otherwise. throw `UnmimplementedError` if not implement
/// Return `true` if screenshot capabilities has been
/// successfully enabled or is currently enabled and `false` otherwise.
/// throw `UnmimplementedError` if not implement
///
@override
Future<bool> screenshotOn() {
return _instancePlatform.screenshotOn();
}

///Return `true` if screenshot capabilities has been successfully toggle from it previous state and
///`false` if the attempt to toggle failed. throw `UnmimplementedError` if not implement
/// Return `true` if screenshot capabilities has been
/// successfully toggle from it previous state and `false` if the attempt
/// to toggle failed.
/// throw `UnmimplementedError` if not implement
///
@override
Future<bool> toggleScreenshot() {
return _instancePlatform.toggleScreenshot();
}

/// Stream to listen to the increment value
/// Stream to screenshot activities [ScreenshotSnapshot]
///
@override
Stream<ScreenshotSnapshot> get screenshotStream {
return _instancePlatform.screenshotStream;
}

/// Start listening to screenshot activities
@override
Future<void> startScreenshotListening() {
return _instancePlatform.startScreenshotListening();
}

/// Stop listening to screenshot activities
@override
Future<void> stopScreenshotListening() {
return _instancePlatform.stopScreenshotListening();
}

@override
bool operator ==(Object other) {
return identical(this, other) ||
other is NoScreenshot &&
runtimeType == other.runtimeType &&
_instancePlatform == other._instancePlatform;
}

@override
int get hashCode => _instancePlatform.hashCode;
}
13 changes: 10 additions & 3 deletions lib/no_screenshot_platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,24 @@ abstract class NoScreenshotPlatform extends PlatformInterface {
Future<bool> toggleScreenshot() {
throw UnimplementedError('toggleScreenshot() has not been implemented.');
}
/// Stream to listen to the increment value

/// Stream to screenshot activities [ScreenshotSnapshot]
/// This stream will emit a [ScreenshotSnapshot] whenever a screenshot is taken.
/// The [ScreenshotSnapshot] contains the path to the screenshot file.
/// throw `UnmimplementedError` if not implement
Stream<ScreenshotSnapshot> get screenshotStream {
throw UnimplementedError('incrementStream has not been implemented.');
}

// Start listening to screenshot activities
Future<void> startScreenshotListening() {
throw UnimplementedError('startScreenshotListening has not been implemented.');
throw UnimplementedError(
'startScreenshotListening has not been implemented.');
}

/// Stop listening to screenshot activities
Future<void> stopScreenshotListening() {
throw UnimplementedError('stopScreenshotListening has not been implemented.');
throw UnimplementedError(
'stopScreenshotListening has not been implemented.');
}
}
Loading

0 comments on commit 0fda76f

Please sign in to comment.