Skip to content

Instantly share code, notes, and snippets.

@hasnainmakada-99
Created August 8, 2023 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasnainmakada-99/cb2fe8301f76857971e40469cf32f677 to your computer and use it in GitHub Desktop.
Save hasnainmakada-99/cb2fe8301f76857971e40469cf32f677 to your computer and use it in GitHub Desktop.
Flutter Google Docs Clone Code
import 'dart:async';
import '../utilities/colors.dart';
import '../common/widgets/loader.dart';
import '../models/DocumentModel.dart';
import '../models/ErrorModel.dart';
import '../repository/AuthRepository.dart';
import '../repository/documentRepository.dart';
import '../repository/socket_repository.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_quill/flutter_quill.dart' as quill;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:routemaster/routemaster.dart';
class DocumentScreen extends ConsumerStatefulWidget {
final String id;
const DocumentScreen({
Key? key,
required this.id,
}) : super(key: key);
@override
ConsumerState<ConsumerStatefulWidget> createState() => _DocumentScreenState();
}
class _DocumentScreenState extends ConsumerState<DocumentScreen> {
TextEditingController titleController =
TextEditingController(text: 'Untitled Document');
quill.QuillController? _controller;
ErrorModel? errorModel;
SocketRepository socketRepository = SocketRepository();
@override
void initState() {
super.initState();
socketRepository.joinRoom(widget.id);
fetchDocumentData();
socketRepository.changeListener((data) {
_controller?.compose(
quill.Delta.fromJson(data['delta']),
_controller?.selection ?? const TextSelection.collapsed(offset: 0),
quill.ChangeSource.REMOTE,
);
});
Timer.periodic(const Duration(seconds: 2), (timer) {
socketRepository.autoSave(<String, dynamic>{
'delta': _controller!.document.toDelta(),
'room': widget.id,
});
});
}
void fetchDocumentData() async {
errorModel = await ref.read(documentRepositoryProvider).getDocumentById(
ref.read(userProvider)!.token,
widget.id,
);
if (errorModel!.data != null) {
titleController.text = (errorModel!.data as DocumentModel).title;
_controller = quill.QuillController(
document: errorModel!.data.content.isEmpty
? quill.Document()
: quill.Document.fromDelta(
quill.Delta.fromJson(errorModel!.data.content),
),
selection: const TextSelection.collapsed(offset: 0),
);
setState(() {});
}
_controller!.document.changes.listen((change) {
if (change.source == quill.ChangeSource.LOCAL) {
Map<String, dynamic> map = {
'delta': change.change,
'room': widget.id,
};
socketRepository.typing(map);
}
});
}
@override
void dispose() {
super.dispose();
titleController.dispose();
}
void updateTitle(WidgetRef ref, String title) {
ref.read(documentRepositoryProvider).updateTitle(
token: ref.read(userProvider)!.token,
id: widget.id,
title: title,
);
}
@override
Widget build(BuildContext context) {
if (_controller == null) {
return const Scaffold(body: Loader());
}
return Scaffold(
appBar: AppBar(
backgroundColor: kWhiteColor,
elevation: 0,
actions: [
Padding(
padding: const EdgeInsets.all(10.0),
child: ElevatedButton.icon(
onPressed: () {
Clipboard.setData(
ClipboardData(
text: 'http://localhost:3000/#/document/${widget.id}'),
).then(
(value) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Link copied!',
),
),
);
},
);
},
icon: const Icon(
Icons.lock,
size: 16,
),
label: const Text('Share'),
style: ElevatedButton.styleFrom(
backgroundColor: kBlueColor,
),
),
),
],
title: Padding(
padding: const EdgeInsets.symmetric(vertical: 9.0),
child: Row(
children: [
GestureDetector(
onTap: () {
Routemaster.of(context).replace('/');
},
child: Image.asset(
'assets/images/docs-logo.png',
height: 40,
),
),
const SizedBox(width: 10),
SizedBox(
width: 180,
child: TextField(
controller: titleController,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: kBlueColor,
),
),
contentPadding: EdgeInsets.only(left: 10),
),
onSubmitted: (value) => updateTitle(ref, value),
),
),
],
),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(1),
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: kGreyColor,
width: 0.1,
),
),
),
),
),
body: Center(
child: Column(
children: [
const SizedBox(height: 10),
quill.QuillToolbar.basic(controller: _controller!),
const SizedBox(height: 10),
Expanded(
child: SizedBox(
width: 750,
child: Card(
color: kWhiteColor,
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(30.0),
child: quill.QuillEditor.basic(
controller: _controller!,
readOnly: false,
),
),
),
),
)
],
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment