') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - Blue-Cheesecake/flutter_timer_camera: A Flutter package that allows you to open the camera and capture images with a timer logic. Perfect for those moments when you need a delay before the shot! · GitHub
Skip to content

Repository files navigation

Flutter Timer Camera

A Flutter package that allows you to open the camera and capture image with a timer logic.

AndroidiOS
SupportSDK 21+iOS 11.0 +

we support only these versions since this package adopts the camera plugin

Features

  • Open the customized camera directly from Flutter app.
  • Set a timer to delay the capture.
  • Switch camera front and back.

Installation

To use this package, add flutter_timer_camera as a dependency in your pubspec.yaml file.

dependencies:
flutter_timer_camera: ^1.0.3

iOS

Add camera usage description on ios/Runner/Info.plist.

<key>NSCameraUsageDescription</key><string>describe why you use camera access</string>

Android

Change minimumSdk version to at least 21

minSdkVersion 21

Usage

import'package:flutter_timer_camera/flutter_timer_camera.dart';
.
.
.
ElevatedButton(
onPressed: () {
showTimerCamera(
context: context,
onSubmit: (Xfile? capturedImage) {
setState(() {
currentImage = capturedImage;
});
},
);
},
child:constText('Open Camera'),
),

Parameters for showTimerCamera

ParameterDescription
BuildContext contextThe BuildContext in which the bottom sheet is shown.
OnCapturedImageCallback onSubmitCallback function that's triggered when an image is captured.
bool enableDrag = falseSpecifies if the bottom sheet can be dragged. Defaults to false.
VoidCallback? onCameraAccessDeniedCallback for handling unauthorized camera access.
BoxFit? imageFitDefines how the captured image should fit within the bounds of the camera view.
Widget? backButtonOnNormalCustom widget for the back button in its normal state.
Widget? backButtonOnCapturedCustom widget for the back button in the captured image state.
Widget? switchCameraButtonCustom widget for the switch camera button.
ButtonStyle? switchCameraButtonStyleStyle for the switch camera button.
Alignment? captureButtonAlignmentAlignment for the capture button.
Widget? onNormalButtonCustom widget for the capture button in its normal state.
Widget? onCountingButtonCustom widget for the capture button during countdown.
Widget? onCapturedButtonCustom widget for the capture button in the captured state.
Alignment? timerOptionAlignmentAlignment for timer options.
TimerOptionStyleParamsModel? timerOptionStyleParamsModelStyling parameters for timer options.
TextStyle? counterTextStyleText style for the countdown timer.
List? timerOptionsList of timer options for capturing images.
double? captureButtonPaddingHeightPadding height for the capture button from the bottom.
double? timerOptionPaddingHeightPadding height for the timer options from the captured button.
Alignment? counterTextAlignmentAlignment for the countdown timer text.
EdgeInsetsGeometry? actionButtonPaddingPadding for action buttons.
int defaultTimerOptionIndex = 0Default selected index for timer options.
bool useSafeArea = trueDetermines whether to respect safe area insets. Defaults to true.
bool isDismissble = trueIndicates whether the sheet is dismissible. Defaults to true.
bool useRootNavigator = falseEnsures that the root navigator is used for navigation when true.

Contributing

Any kind of pull requests are welcome. Feel free to fork the project, open issues, and submit PRs.

License

The 3-Clause BSD

About

A Flutter package that allows you to open the camera and capture images with a timer logic. Perfect for those moments when you need a delay before the shot!

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages