Initial commit

This commit is contained in:
Paul Schaub 2018-01-27 03:33:50 +01:00
commit e069ad22de
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
252 changed files with 1700 additions and 0 deletions

1
mobile/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

44
mobile/build.gradle Normal file
View file

@ -0,0 +1,44 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "de.vanitasvitae.slam"
minSdkVersion 21
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
//implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.0.2'
implementation 'com.android.support:design:27.0.2'
implementation 'com.android.support:support-v4:27.0.2'
implementation 'com.android.support:support-v13:27.0.2'
implementation 'com.android.support:cardview-v7:27.0.2'
implementation 'com.android.support:recyclerview-v7:27.0.2'
implementation 'com.android.support:support-emoji:27.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//compile "org.igniterealtime.smack:smack-android-extensions:$smackVersion"
//compile "org.igniterealtime.smack:smack-omemo-signal:$smackVersion"
//compile "org.igniterealtime.smack:smack-tcp:$smackVersion"
//compile "org.igniterealtime.smack:smack-experimental:$smackVersion"
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
compile 'de.hdodenhof:circleimageview:2.0.0'
}

21
mobile/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,26 @@
package de.vanitasvitae.slam;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("de.vanitasvitae.slam", appContext.getPackageName());
}
}

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.vanitasvitae.slam">
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Slam">
<activity
android:name=".activity.LoginActivity"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.MainActivity" />
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
<service android:name=".service.MyMessagingService"></service>
<receiver android:name=".receiver.MessageReadReceiver">
<intent-filter>
<action android:name="de.vanitasvitae.slam.ACTION_MESSAGE_READ" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.MessageReplyReceiver">
<intent-filter>
<action android:name="de.vanitasvitae.slam.ACTION_MESSAGE_REPLY" />
</intent-filter>
</receiver>
</application>
</manifest>

View file

@ -0,0 +1,60 @@
package de.vanitasvitae.slam.activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.TextInputEditText;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import de.vanitasvitae.slam.R;
public class LoginActivity extends ThemedAppCompatActivity {
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.login_username)
TextInputEditText inputUsername;
@BindView(R.id.login_password)
TextInputEditText inputPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
inputPassword.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
login();
return true;
}
return false;
}
});
}
@OnClick(R.id.button_login)
void login() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_login, menu);
return true;
}
}

View file

@ -0,0 +1,55 @@
package de.vanitasvitae.slam.activity;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.vanitasvitae.slam.R;
/**
* Created by vanitas on 22.01.18.
*/
public class MainActivity extends ThemedAppCompatActivity {
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.navigation_view)
NavigationView navigationView;
@BindView(R.id.drawer_layout)
DrawerLayout drawerLayout;
private ActionBarDrawerToggle drawerToggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
drawerToggle = new ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.error_incorrect_password, R.string.error_invalid_jid);
drawerLayout.addDrawerListener(drawerToggle);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
}

View file

@ -0,0 +1,84 @@
package de.vanitasvitae.slam.activity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import java.util.Arrays;
import de.vanitasvitae.slam.R;
/**
* Created by Paul Schaub on 27.01.18.
*/
public abstract class ThemedAppCompatActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String PREF_APP_THEME = "pref_app_theme";
private static final String THEME_LIGHT = "defaultTheme";
private static final String THEME_DARK = "darkTheme";
private SharedPreferences preferences;
@SuppressLint("ApplySharedPref")
protected void onCreate(Bundle savedInstanceState) {
preferences = PreferenceManager.getDefaultSharedPreferences(this);
String theme = preferences.getString(PREF_APP_THEME, THEME_LIGHT);
switch (theme) {
case THEME_DARK:
setTheme(R.style.Slam_Dark);
break;
// add more themes here...
default:
setTheme(R.style.Slam);
}
super.onCreate(savedInstanceState);
}
@Override
protected void onPause() {
preferences.unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
protected void onResume() {
preferences.registerOnSharedPreferenceChangeListener(this);
super.onResume();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.debug_switch_theme:
toggleTheme();
return true;
}
return super.onOptionsItemSelected(item);
}
public void toggleTheme() {
// ...and here
String[] themes = new String[]{THEME_LIGHT, THEME_DARK};
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
String current = pref.getString(PREF_APP_THEME, THEME_LIGHT);
int index = Arrays.asList(themes).indexOf(current);
String next = themes[(index + 1) % themes.length];
pref.edit().putString(PREF_APP_THEME, next).apply();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(PREF_APP_THEME)) {
finish();
final Intent intent = getIntent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.vanitasvitae.slam.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import de.vanitasvitae.slam.service.MyMessagingService;
public class MessageReadReceiver extends BroadcastReceiver {
private static final String TAG = MessageReadReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
if (MyMessagingService.READ_ACTION.equals(intent.getAction())) {
int conversationId = intent.getIntExtra(MyMessagingService.CONVERSATION_ID, -1);
if (conversationId != -1) {
Log.d(TAG, "Conversation " + conversationId + " was read");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(conversationId);
}
}
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.vanitasvitae.slam.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.RemoteInput;
import android.util.Log;
import de.vanitasvitae.slam.service.MyMessagingService;
/**
* A receiver that gets called when a reply is sent to a given conversationId
*/
public class MessageReplyReceiver extends BroadcastReceiver {
private static final String TAG = MessageReplyReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
if (MyMessagingService.REPLY_ACTION.equals(intent.getAction())) {
int conversationId = intent.getIntExtra(MyMessagingService.CONVERSATION_ID, -1);
CharSequence reply = getMessageText(intent);
Log.d(TAG, "Got reply (" + reply + ") for ConversationId " + conversationId);
}
}
/**
* Get the message text from the intent.
* Note that you should call {@code RemoteInput#getResultsFromIntent(intent)} to process
* the RemoteInput.
*/
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(MyMessagingService.EXTRA_VOICE_REPLY);
}
return null;
}
}

View file

@ -0,0 +1,119 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.vanitasvitae.slam.service;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.CarExtender;
import android.support.v4.app.NotificationCompat.CarExtender.UnreadConversation;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.RemoteInput;
public class MyMessagingService extends Service {
public static final String READ_ACTION =
"de.vanitasvitae.slam.ACTION_MESSAGE_READ";
public static final String REPLY_ACTION =
"de.vanitasvitae.slam.ACTION_MESSAGE_REPLY";
public static final String CONVERSATION_ID = "conversation_id";
public static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
private static final String TAG = MyMessagingService.class.getSimpleName();
private final Messenger mMessenger = new Messenger(new IncomingHandler());
private NotificationManagerCompat mNotificationManager;
@Override
public void onCreate() {
mNotificationManager = NotificationManagerCompat.from(getApplicationContext());
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
private Intent createIntent(int conversationId, String action) {
return new Intent()
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
.setAction(action)
.putExtra(CONVERSATION_ID, conversationId);
}
private void sendNotification(int conversationId, String message,
String participant, long timestamp) {
// A pending Intent for reads
PendingIntent readPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
conversationId,
createIntent(conversationId, READ_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);
// Build a RemoteInput for receiving voice input in a Car Notification
RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
.setLabel("Reply by voice")
.build();
// Building a Pending Intent for the reply action to trigger
PendingIntent replyIntent = PendingIntent.getBroadcast(getApplicationContext(),
conversationId,
createIntent(conversationId, REPLY_ACTION),
PendingIntent.FLAG_UPDATE_CURRENT);
// Create the UnreadConversation and populate it with the participant name,
// read and reply intents.
UnreadConversation.Builder unreadConvBuilder =
new UnreadConversation.Builder(participant)
.setLatestTimestamp(timestamp)
.setReadPendingIntent(readPendingIntent)
.setReplyAction(replyIntent, remoteInput);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext())
// Set the application notification icon:
//.setSmallIcon(R.drawable.notification_icon)
// Set the large icon, for example a picture of the other recipient of the message
//.setLargeIcon(personBitmap)
.setContentText(message)
.setWhen(timestamp)
.setContentTitle(participant)
.setContentIntent(readPendingIntent)
.extend(new CarExtender()
.setUnreadConversation(unreadConvBuilder.build()));
mNotificationManager.notify(conversationId, builder.build());
}
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
sendNotification(1, "This is a sample message", "John Doe",
System.currentTimeMillis());
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

View file

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Some files were not shown because too many files have changed in this diff Show more