Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
krille-chan committed Jun 9, 2019
0 parents commit 77be610
Show file tree
Hide file tree
Showing 22 changed files with 2,591 additions and 0 deletions.
70 changes: 70 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# Visual Studio Code related
.vscode/

# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
build/

# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java

# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*

# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
18 changes: 18 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
image: cirrusci/flutter

stages:
- coverage

variables:
LC_ALL: "en_US.UTF-8"
LANG: "en_US.UTF-8"

coverage:
stage: coverage
coverage: '/^\s+lines.+: (\d+.\d*%)/'
dependencies: []
script:
- sudo apt-get update -qq && sudo apt-get install -qq apt-transport-https curl gnupg lcov git
- ./scripts/test.sh
- ./scripts/coverage.sh
- flutter pub pub publish --dry-run
10 changes: 10 additions & 0 deletions .metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b
channel: stable

project_type: package
84 changes: 84 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# fluffyfluttermatrix

Dead simple Flutter widget to use Matrix.org in your Flutter app.

## How to use this

1. Use the Matrix widget as root for your widget tree:

```dart
import 'package:flutter/material.dart';
import 'package:fluffyfluttermatrix/fluffyfluttermatrix.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FluffyMatrix(
child: MaterialApp(
title: 'Welcome to Flutter'
),
);
}
}
```

2. Access the MatrixState object by calling Matrix.of with your current BuildContext:

```dart
Client matrix = Matrix.of(context);
```

3. Connect to a Matrix Homeserver and listen to the streams:

```dart
matrix.homeserver = "https://yourhomeserveraddress";
matrix.onLoginStateChanged.stream.listen((bool loginState){
print("LoginState: ${loginState.toString()}");
});
matrix.onEvent.stream.listen((EventUpdate eventUpdate){
print("New event update!");
});
matrix.onRoomUpdate.stream.listen((RoomUpdate eventUpdate){
print("New room update!");
});
final loginResp = await matrix.jsonRequest(
type: "POST",
action: "/client/r0/login",
data: {
"type": "m.login.password",
"user": _usernameController.text,
"password": _passwordController.text,
"initial_device_display_name": "Fluffy Matrix Client"
}
);
matrix.connect(
newToken: loginResp["token"],
newUserID: loginResp["user_id"],
newHomeserver: matrix.homeserver,
newDeviceName: "Fluffy Matrix Client",
newDeviceID: loginResp["device_id"],
newMatrixVersions: ["r0.4.0"],
newLazyLoadMembers: false
);
```

4. Send a message to a Room:

```dart
final resp = await jsonRequest(
type: "PUT",
action: "/r0/rooms/!fjd823j:example.com/send/m.room.message/$txnId",
data: {
"msgtype": "m.text",
"body": "hello"
}
);
```
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TODO: Add your license here.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# famedlysdk

A new Flutter package.

## Getting Started

This project is a starting point for a Dart
[package](https://flutter.dev/developing-packages/),
a library module containing code that can be shared easily across
multiple Flutter or Dart projects.

For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
13 changes: 13 additions & 0 deletions lib/famedlysdk.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
library famedlysdk;

export 'package:famedlysdk/src/responses/ErrorResponse.dart';
export 'package:famedlysdk/src/sync/RoomUpdate.dart';
export 'package:famedlysdk/src/sync/EventUpdate.dart';
export 'package:famedlysdk/src/utils/ChatTime.dart';
export 'package:famedlysdk/src/utils/MxContent.dart';
export 'package:famedlysdk/src/Client.dart';
export 'package:famedlysdk/src/Connection.dart';
export 'package:famedlysdk/src/Event.dart';
export 'package:famedlysdk/src/Room.dart';
export 'package:famedlysdk/src/Store.dart';
export 'package:famedlysdk/src/User.dart';
169 changes: 169 additions & 0 deletions lib/src/Client.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import 'dart:async';
import 'dart:convert';
import 'dart:core';
import 'package:flutter/material.dart';
import 'responses/ErrorResponse.dart';
import 'Connection.dart';
import 'Store.dart';

/// Represents a Matrix connection to communicate with a
/// [Matrix](https://matrix.org) homeserver and is the entry point for this
/// SDK.
class Client {

/// Handles the connection for this client.
Connection connection;

/// Optional persistent store for all data.
Store store;

Client(this.clientName) {
connection = Connection(this);

if (this.clientName != "testclient")
store = Store(this);
connection.onLoginStateChanged.stream.listen((loginState) {
print("LoginState: ${loginState.toString()}");
});
}

/// The required name for this client.
final String clientName;

/// The homeserver this client is communicating with.
String homeserver;

/// The Matrix ID of the current logged user.
String userID;

/// This is the access token for the matrix client. When it is undefined, then
/// the user needs to sign in first.
String accessToken;

/// This points to the position in the synchronization history.
String prevBatch;

/// The device ID is an unique identifier for this device.
String deviceID;

/// The device name is a human readable identifier for this device.
String deviceName;

/// Which version of the matrix specification does this server support?
List<String> matrixVersions;

/// Wheither the server supports lazy load members.
bool lazyLoadMembers = false;

/// Returns the current login state.
bool isLogged() => accessToken != null;

/// Checks the supported versions of the Matrix protocol and the supported
/// login types. Returns false if the server is not compatible with the
/// client. Automatically sets [matrixVersions] and [lazyLoadMembers].
Future<bool> checkServer(serverUrl) async {
homeserver = serverUrl;

final versionResp =
await connection.jsonRequest(type: "GET", action: "/client/versions");
if (versionResp is ErrorResponse) {
connection.onError.add(ErrorResponse(errcode: "NO_RESPONSE", error: ""));
return false;
}

final List<String> versions = List<String>.from(versionResp["versions"]);

if (versions == null) {
connection.onError.add(ErrorResponse(errcode: "NO_RESPONSE", error: ""));
return false;
}

for (int i = 0; i < versions.length; i++) {
if (versions[i] == "r0.4.0")
break;
else if (i == versions.length - 1) {
connection.onError.add(ErrorResponse(errcode: "NO_SUPPORT", error: ""));
return false;
}
}

matrixVersions = versions;

if (versionResp.containsKey("unstable_features") &&
versionResp["unstable_features"].containsKey("m.lazy_load_members")) {
lazyLoadMembers = versionResp["unstable_features"]["m.lazy_load_members"]
? true
: false;
}

final loginResp =
await connection.jsonRequest(type: "GET", action: "/client/r0/login");
if (loginResp is ErrorResponse) {
connection.onError.add(loginResp);
return false;
}

final List<dynamic> flows = loginResp["flows"];

for (int i = 0; i < flows.length; i++) {
if (flows[i].containsKey("type") &&
flows[i]["type"] == "m.login.password")
break;
else if (i == flows.length - 1) {
connection.onError.add(ErrorResponse(errcode: "NO_SUPPORT", error: ""));
return false;
}
}

return true;
}

/// Handles the login and allows the client to call all APIs which require
/// authentication. Returns false if the login was not successful.
Future<bool> login(String username, String password) async {

final loginResp =
await connection.jsonRequest(type: "POST", action: "/client/r0/login", data: {
"type": "m.login.password",
"user": username,
"identifier": {
"type": "m.id.user",
"user": username,
},
"password": password,
"initial_device_display_name": "Famedly Talk"
});

if (loginResp is ErrorResponse) {
connection.onError.add(loginResp);
return false;
}

final userID = loginResp["user_id"];
final accessToken = loginResp["access_token"];
if (userID == null || accessToken == null) {
connection.onError.add(ErrorResponse(errcode: "NO_SUPPORT", error: ""));
}

await connection.connect(
newToken: accessToken,
newUserID: userID,
newHomeserver: homeserver,
newDeviceName: "",
newDeviceID: "",
newMatrixVersions: matrixVersions,
newLazyLoadMembers: lazyLoadMembers);
return true;
}

/// Sends a logout command to the homeserver and clears all local data,
/// including all persistent data from the store.
Future<void> logout() async {
final dynamic resp =
await connection.jsonRequest(type: "POST", action: "/client/r0/logout/all");
if (resp == null) return;

await connection.clear();
}

}
Loading

0 comments on commit 77be610

Please sign in to comment.