ridu

 avatar
unknown
dart
a year ago
8.5 kB
1
Indexable
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() => runApp(MyBrowserApp());

class MyBrowserApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple Browser',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BrowserPage(),
    );
  }
}

class BrowserPage extends StatefulWidget {
  @override
  _BrowserPageState createState() => _BrowserPageState();
}

class _BrowserPageState extends State<BrowserPage> {
  final TextEditingController _controller = TextEditingController();
  List<WebViewController> _tabs = [];
  List<String> _titles = [];
  int _currentTabIndex = 0;
  bool _showHomePage = true;

  @override
  void initState() {
    super.initState();
    _addNewTab(showHomePage: true);
  }

  void _addNewTab({bool showHomePage = false}) {
    WebViewController webViewController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(NavigationDelegate(
        onProgress: (int progress) {},
        onPageStarted: (String url) {
          _updateLoading(url);
          _updateTitle('Loading...', _currentTabIndex);
        },
        onPageFinished: (String url) {
          _updatePageTitle(_currentTabIndex);
        },
        onWebResourceError: (WebResourceError error) {},
        onNavigationRequest: (NavigationRequest request) {
          return NavigationDecision.navigate;
        },
      ));
    setState(() {
      _tabs.add(webViewController);
      _titles.add('New Tab');
      _currentTabIndex = _tabs.length - 1;
      _showHomePage = showHomePage;
    });
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        appBar: AppBar(
          title: _showHomePage
            ? Text('Homepage')
            : TextField(
                controller: _controller,
                decoration: InputDecoration(hintText: 'Enter a URL or search'),
                onSubmitted: (input) => _loadSearch(input),
              ),
        ),
        body: _showHomePage ? buildHomePage() : WebViewWidget(controller: _tabs[_currentTabIndex]),
        bottomNavigationBar: buildBottomNavigationBar(),
      ),
    );
  }

  Widget buildHomePage() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: TextField(
              decoration: InputDecoration(
                hintText: 'Enter a URL or search',
                border: OutlineInputBorder(),
              ),
              onSubmitted: (input) => _loadSearch(input),
            ),
          ),
          Wrap(
            spacing: 10.0,
            children: <Widget>[
              _quickAccessButton('Facebook', 'https://facebook.com'),
              _quickAccessButton('Twitter', 'https://twitter.com'),
              _quickAccessButton('YouTube', 'https://youtube.com'),
              _quickAccessButton('Gmail', 'https://mail.google.com'),
            ],
          ),
        ],
      ),
    );
  }

  Widget _quickAccessButton(String name, String url) {
    return ElevatedButton(
      onPressed: () => _loadUrl(url),
      child: Text(name),
    );
  }

  void _loadSearch(String input) {
    if (_isValidUrl(input)) {
      _loadUrl(input.contains('://') ? input : 'https://$input');
    } else {
      _loadUrl('https://www.google.com/search?q=${Uri.encodeComponent(input)}');
    }
  }

  void _loadUrl(String url) {
    final Uri uri = Uri.parse(url);
    if (uri.scheme.contains('http')) {
      _tabs[_currentTabIndex].loadRequest(Uri.parse(url));
      setState(() => _showHomePage = false);
    }
  }

  bool _isValidUrl(String url) {
    final Uri? uri = Uri.tryParse(url);
    return uri != null && (uri.scheme == 'http' || uri.scheme == 'https');
  }

  BottomNavigationBar buildBottomNavigationBar() {
    return BottomNavigationBar(
      backgroundColor: Colors.white,
      selectedItemColor: Colors.black,
      unselectedItemColor: Colors.black,
      items: <BottomNavigationBarItem>[
        BottomNavigationBarItem(
          icon: Icon(Icons.arrow_back),
          label: 'Back',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.arrow_forward),
          label: 'Forward',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          label: 'Home',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.refresh),
          label: 'Reload',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.tab),
          label: 'Tabs',
        ),
      ],
      onTap: (index) => _handleNavBarTap(index),
    );
  }

  void _handleNavBarTap(int index) {
    if (index == 4) {
      _showTabDialog();
    } else {
      switch (index) {
        case 0: // Back
          _handleBack();
          break;
        case 1: // Forward
          _tabs[_currentTabIndex].goForward();
          break;
        case 2: // Home
          setState(() => _showHomePage = true);
          break;
        case 3: // Reload
          _tabs[_currentTabIndex].reload();
          break;
      }
    }
  }

  Future<void> _handleBack() async {
    if (await _tabs[_currentTabIndex].canGoBack()) {
      _tabs[_currentTabIndex].goBack();
    } else {
      setState(() => _showHomePage = true);
    }
  }

  void _showTabDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Open Tabs'),
          content: Container(
            width: double.maxFinite,
            child: ListView.builder(
              itemCount: _tabs.length,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  title: Text('Tab ${index + 1} - ${_titles[index]}'),
                  trailing: index != _currentTabIndex ? IconButton(
                    icon: Icon(Icons.close),
                    onPressed: () => _closeTab(index),
                  ) : null,
                  onTap: () {
                    setState(() {
                      _currentTabIndex = index;
                      _showHomePage = false;
                    });
                    Navigator.of(context).pop();
                  },
                );
              },
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: Text('New Tab'),
              onPressed: () {
                Navigator.of(context).pop();
                _addNewTab(showHomePage: true);
              },
            ),
          ],
        );
      },
    );
  }

  void _closeTab(int index) {
    if (_tabs.length > 1) {
      setState(() {
        _tabs.removeAt(index);
        _titles.removeAt(index);
        _currentTabIndex = 0; // Switch to the first tab
        _showHomePage = true;
      });
    }
    Navigator.of(context).pop();
  }

  void _updateLoading(String url) {
    setState(() {
      _controller.text = url;
      _showHomePage = false;
    });
  }

  void _updatePageTitle(int tabIndex) {
    _tabs[tabIndex].runJavaScriptReturningResult('document.title').then((result) {
      String title = result is String ? result : 'No Title';
      setState(() {
        _titles[tabIndex] = title;
      });
    });
  }

  void _updateTitle(String title, int tabIndex) {
    setState(() {
      _titles[tabIndex] = title;
    });
  }

  Future<bool> _onWillPop() async {
    if (!_showHomePage) {
      if (await _tabs[_currentTabIndex].canGoBack()) {
        _tabs[_currentTabIndex].goBack();
        return false; // Prevent exiting the app
      } else {
        setState(() => _showHomePage = true);
        return false; // Prevent exiting the app
      }
    } else {
      return (await showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: Text('Exit Browser'),
          content: Text('Are you sure you want to exit the browser?'),
          actions: <Widget>[
            TextButton(
              child: Text('No'),
              onPressed: () => Navigator.of(context).pop(false),
            ),
            TextButton(
              child: Text('Yes'),
              onPressed: () => Navigator.of(context).pop(true),
            ),
          ],
        ),
      )) ?? false;
    }
  }
}
Leave a Comment