Merge branch 'develop'

This commit is contained in:
tom79 2019-05-31 19:15:15 +02:00
commit 9a218ba5af
126 changed files with 3132 additions and 190 deletions

View File

@ -6,8 +6,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 274
versionName "2.2.0"
versionCode 276
versionName "2.3.0"
multiDexEnabled true
renderscriptTargetApi 28 as int
renderscriptSupportModeEnabled true
@ -102,4 +102,6 @@ dependencies {
implementation 'com.github.stom79:horizontalbargraph:1.5'
implementation 'jp.wasabeef:glide-transformations:4.0.0'
playstoreImplementation "io.github.kobakei:ratethisapp:$ratethisappLibraryVersion"
implementation 'ja.burhanrashid52:photoeditor:0.3.3'
implementation 'com.github.yalantis:ucrop:2.2.3'
}

View File

@ -161,6 +161,15 @@
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity android:name="app.fedilab.android.activities.PhotoEditorActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<activity android:name="app.fedilab.android.activities.WebviewActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenSize"

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@ -1,15 +1,26 @@
package app.fedilab.android.activities;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import com.franmontiel.localechanger.LocaleChanger;
import com.vanniktech.emoji.EmojiManager;
import com.vanniktech.emoji.one.EmojiOneProvider;
import app.fedilab.android.helper.Helper;
import es.dmoral.toasty.Toasty;
/**
* Created by Thomas on 12/12/2017.
@ -18,6 +29,11 @@ import app.fedilab.android.helper.Helper;
@SuppressLint("Registered")
public class BaseActivity extends AppCompatActivity {
public static final int READ_WRITE_STORAGE = 52;
private ProgressDialog mProgressDialog;
static {
Helper.installProvider();
EmojiManager.install(new EmojiOneProvider());
@ -34,4 +50,52 @@ public class BaseActivity extends AppCompatActivity {
newBase = LocaleChanger.configureBaseContext(newBase);
super.attachBaseContext(newBase);
}
public boolean requestPermission(String permission) {
boolean isGranted = ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
if (!isGranted) {
ActivityCompat.requestPermissions(
this,
new String[]{permission},
READ_WRITE_STORAGE);
}
return isGranted;
}
public void isPermissionGranted(boolean isGranted, String permission) {
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case READ_WRITE_STORAGE:
isPermissionGranted(grantResults[0] == PackageManager.PERMISSION_GRANTED, permissions[0]);
break;
}
}
protected void showLoading(@NonNull String message) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(message);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
protected void hideLoading() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
}
protected void showSnackbar(@NonNull String message) {
View view = findViewById(android.R.id.content);
if (view != null) {
Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show();
} else {
Toasty.info(this, message, Toast.LENGTH_SHORT).show();
}
}
}

View File

@ -0,0 +1,516 @@
package app.fedilab.android.activities;
/* Copyright 2017 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Window;
import app.fedilab.android.R;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.imageeditor.EmojiBSFragment;
import app.fedilab.android.imageeditor.PropertiesBSFragment;
import app.fedilab.android.imageeditor.StickerBSFragment;
import app.fedilab.android.imageeditor.TextEditorDialogFragment;
import app.fedilab.android.imageeditor.filters.FilterListener;
import app.fedilab.android.imageeditor.filters.FilterViewAdapter;
import app.fedilab.android.imageeditor.tools.EditingToolsAdapter;
import app.fedilab.android.imageeditor.tools.ToolType;
import ja.burhanrashid52.photoeditor.PhotoEditor;
import ja.burhanrashid52.photoeditor.PhotoEditorView;
import ja.burhanrashid52.photoeditor.PhotoFilter;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.provider.MediaStore;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.transition.ChangeBounds;
import android.support.transition.TransitionManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.animation.AnticipateOvershootInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.yalantis.ucrop.UCrop;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import ja.burhanrashid52.photoeditor.OnPhotoEditorListener;
import ja.burhanrashid52.photoeditor.SaveSettings;
import ja.burhanrashid52.photoeditor.ViewType;
public class PhotoEditorActivity extends BaseActivity implements OnPhotoEditorListener,
View.OnClickListener,
PropertiesBSFragment.Properties,
EmojiBSFragment.EmojiListener,
StickerBSFragment.StickerListener, EditingToolsAdapter.OnItemSelected, FilterListener {
private static final int CAMERA_REQUEST = 52;
private static final int PICK_REQUEST = 53;
private PhotoEditor mPhotoEditor;
private PhotoEditorView mPhotoEditorView;
private PropertiesBSFragment mPropertiesBSFragment;
private EmojiBSFragment mEmojiBSFragment;
private StickerBSFragment mStickerBSFragment;
private TextView mTxtCurrentTool;
private RecyclerView mRvTools, mRvFilters;
private EditingToolsAdapter mEditingToolsAdapter = new EditingToolsAdapter(this);
private FilterViewAdapter mFilterViewAdapter = new FilterViewAdapter(this);
private ConstraintLayout mRootView;
private ConstraintSet mConstraintSet = new ConstraintSet();
private boolean mIsFilterVisible;
private Uri uri;
private String tempname;
private boolean exit;
@SuppressLint("MissingPermission")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
switch (theme){
case Helper.THEME_LIGHT:
setTheme(R.style.AppTheme);
break;
case Helper.THEME_DARK:
setTheme(R.style.AppThemeDark);
break;
case Helper.THEME_BLACK:
setTheme(R.style.AppThemeBlack);
break;
default:
setTheme(R.style.AppThemeDark);
}
Bundle b = getIntent().getExtras();
if( getSupportActionBar() != null)
getSupportActionBar().hide();
String path = null;
if(b != null)
path = b.getString("imageUri", null);
if( path == null) {
finish();
}
uri = Uri.parse(path);
exit = false;
setContentView(R.layout.activity_photoeditor);
initViews();
mPropertiesBSFragment = new PropertiesBSFragment();
mEmojiBSFragment = new EmojiBSFragment();
mStickerBSFragment = new StickerBSFragment();
mStickerBSFragment.setStickerListener(this);
mEmojiBSFragment.setEmojiListener(this);
mPropertiesBSFragment.setPropertiesChangeListener(this);
LinearLayoutManager llmTools = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
mRvTools.setLayoutManager(llmTools);
mRvTools.setAdapter(mEditingToolsAdapter);
LinearLayoutManager llmFilters = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
mRvFilters.setLayoutManager(llmFilters);
mRvFilters.setAdapter(mFilterViewAdapter);
Typeface mEmojiTypeFace = Typeface.createFromAsset(getAssets(), "emojione-android.ttf");
mPhotoEditor = new PhotoEditor.Builder(this, mPhotoEditorView)
.setPinchTextScalable(true) // set flag to make text scalable when pinch
.setDefaultEmojiTypeface(mEmojiTypeFace)
.build(); // build photo editor sdk
mPhotoEditor.setOnPhotoEditorListener(this);
//Set Image Dynamically
mPhotoEditorView.getSource().setImageURI(uri);
Button send = findViewById(R.id.send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
exit = true;
saveImage();
}
});
}
private void initViews() {
ImageView imgUndo;
ImageView imgRedo;
ImageView imgCamera;
ImageView imgGallery;
ImageView imgSave;
ImageView imgClose;
mPhotoEditorView = findViewById(R.id.photoEditorView);
mTxtCurrentTool = findViewById(R.id.txtCurrentTool);
mRvTools = findViewById(R.id.rvConstraintTools);
mRvFilters = findViewById(R.id.rvFilterView);
mRootView = findViewById(R.id.rootView);
imgUndo = findViewById(R.id.imgUndo);
imgUndo.setOnClickListener(this);
imgRedo = findViewById(R.id.imgRedo);
imgRedo.setOnClickListener(this);
imgCamera = findViewById(R.id.imgCamera);
imgCamera.setOnClickListener(this);
imgGallery = findViewById(R.id.imgGallery);
imgGallery.setOnClickListener(this);
imgSave = findViewById(R.id.imgSave);
imgSave.setOnClickListener(this);
imgClose = findViewById(R.id.imgClose);
imgClose.setOnClickListener(this);
}
@Override
public void onEditTextChangeListener(final View rootView, String text, int colorCode) {
TextEditorDialogFragment textEditorDialogFragment =
TextEditorDialogFragment.show(this, text, colorCode);
textEditorDialogFragment.setOnTextEditorListener(new TextEditorDialogFragment.TextEditor() {
@Override
public void onDone(String inputText, int colorCode) {
mPhotoEditor.editText(rootView, inputText, colorCode);
mTxtCurrentTool.setText(R.string.label_text);
}
});
}
@Override
public void onAddViewListener(ViewType viewType, int numberOfAddedViews) {
}
@Override
public void onRemoveViewListener(int numberOfAddedViews) {
}
@Override
public void onRemoveViewListener(ViewType viewType, int numberOfAddedViews) {
}
@Override
public void onStartViewChangeListener(ViewType viewType) {
}
@Override
public void onStopViewChangeListener(ViewType viewType) {
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.imgUndo:
mPhotoEditor.undo();
break;
case R.id.imgRedo:
mPhotoEditor.redo();
break;
case R.id.imgSave:
saveImage();
break;
case R.id.imgClose:
onBackPressed();
break;
case R.id.imgCamera:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
break;
case R.id.imgGallery:
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, getString(R.string.toot_select_image)), PICK_REQUEST);
break;
}
}
@SuppressLint("MissingPermission")
private void saveImage() {
if (requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showLoading(getString(R.string.saving));
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
String myDir = sharedpreferences.getString(Helper.SET_FOLDER_RECORD, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
String filename = System.currentTimeMillis()+"_"+Helper.getFileName(PhotoEditorActivity.this, uri);
File file = new File(myDir+"/"+filename);
try {
file.createNewFile();
SaveSettings saveSettings = new SaveSettings.Builder()
.setClearViewsEnabled(true)
.setTransparencyEnabled(true)
.build();
mPhotoEditor.saveAsFile(file.getAbsolutePath(), saveSettings, new PhotoEditor.OnSaveListener() {
@Override
public void onSuccess(@NonNull String imagePath) {
hideLoading();
showSnackbar(getString(R.string.image_saved));
mPhotoEditorView.getSource().setImageURI(Uri.fromFile(new File(imagePath)));
if( exit ){
Intent intentImage = new Intent(Helper.INTENT_SEND_MODIFIED_IMAGE);
intentImage.putExtra("imgpath", imagePath);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intentImage);
finish();
}
}
@Override
public void onFailure(@NonNull Exception exception) {
hideLoading();
showSnackbar(getString(R.string.save_image_failed));
}
});
} catch (IOException e) {
e.printStackTrace();
hideLoading();
showSnackbar(e.getMessage());
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case CAMERA_REQUEST:
mPhotoEditor.clearAllViews();
Bitmap photo = (Bitmap) data.getExtras().get("data");
mPhotoEditorView.getSource().setImageBitmap(photo);
break;
case PICK_REQUEST:
try {
mPhotoEditor.clearAllViews();
Uri uri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
mPhotoEditorView.getSource().setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
break;
case UCrop.REQUEST_CROP:
final Uri resultUri = UCrop.getOutput(data);
if( resultUri != null) {
mPhotoEditorView.getSource().setImageURI(resultUri);
File fdelete = new File(uri.getPath());
if (fdelete.exists()) {
fdelete.delete();
}
uri = resultUri;
String filename = System.currentTimeMillis()+"_"+Helper.getFileName(PhotoEditorActivity.this, uri);
tempname = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(new Date()) + filename;
}
break;
}
}
}
@Override
public void onColorChanged(int colorCode) {
mPhotoEditor.setBrushColor(colorCode);
mTxtCurrentTool.setText(R.string.label_brush);
}
@Override
public void onOpacityChanged(int opacity) {
mPhotoEditor.setOpacity(opacity);
mTxtCurrentTool.setText(R.string.label_brush);
}
@Override
public void onBrushSizeChanged(int brushSize) {
mPhotoEditor.setBrushSize(brushSize);
mTxtCurrentTool.setText(R.string.label_brush);
}
@Override
public void onEmojiClick(String emojiUnicode) {
mPhotoEditor.addEmoji(emojiUnicode);
mTxtCurrentTool.setText(R.string.label_emoji);
}
@Override
public void onStickerClick(Bitmap bitmap) {
mPhotoEditor.addImage(bitmap);
mTxtCurrentTool.setText(R.string.label_sticker);
}
@Override
public void isPermissionGranted(boolean isGranted, String permission) {
if (isGranted) {
saveImage();
}
}
private void showSaveDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage( getString(R.string.confirm_exit_editing));
builder.setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
saveImage();
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setNeutralButton(R.string.discard, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.create().show();
}
@Override
public void onFilterSelected(PhotoFilter photoFilter) {
mPhotoEditor.setFilterEffect(photoFilter);
}
@Override
public void onToolSelected(ToolType toolType) {
switch (toolType) {
case BRUSH:
mPhotoEditor.setBrushDrawingMode(true);
mTxtCurrentTool.setText(R.string.label_brush);
mPropertiesBSFragment.show(getSupportFragmentManager(), mPropertiesBSFragment.getTag());
break;
case TEXT:
TextEditorDialogFragment textEditorDialogFragment = TextEditorDialogFragment.show(this);
textEditorDialogFragment.setOnTextEditorListener(new TextEditorDialogFragment.TextEditor() {
@Override
public void onDone(String inputText, int colorCode) {
mPhotoEditor.addText(inputText, colorCode);
mTxtCurrentTool.setText(R.string.label_text);
}
});
break;
case ERASER:
mPhotoEditor.brushEraser();
mTxtCurrentTool.setText(R.string.label_eraser);
break;
case FILTER:
mTxtCurrentTool.setText(R.string.label_filter);
showFilter(true);
break;
case EMOJI:
mEmojiBSFragment.show(getSupportFragmentManager(), mEmojiBSFragment.getTag());
break;
case STICKER:
mStickerBSFragment.show(getSupportFragmentManager(), mStickerBSFragment.getTag());
break;
case CROP:
String filename = System.currentTimeMillis()+"_"+Helper.getFileName(PhotoEditorActivity.this, uri);
tempname = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(new Date()) + filename;
UCrop.of(uri, Uri.fromFile(new File(getCacheDir(),tempname)))
.start(PhotoEditorActivity.this);
break;
}
}
void showFilter(boolean isVisible) {
mIsFilterVisible = isVisible;
mConstraintSet.clone(mRootView);
if (isVisible) {
mConstraintSet.clear(mRvFilters.getId(), ConstraintSet.START);
mConstraintSet.connect(mRvFilters.getId(), ConstraintSet.START,
ConstraintSet.PARENT_ID, ConstraintSet.START);
mConstraintSet.connect(mRvFilters.getId(), ConstraintSet.END,
ConstraintSet.PARENT_ID, ConstraintSet.END);
} else {
mConstraintSet.connect(mRvFilters.getId(), ConstraintSet.START,
ConstraintSet.PARENT_ID, ConstraintSet.END);
mConstraintSet.clear(mRvFilters.getId(), ConstraintSet.END);
}
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(350);
changeBounds.setInterpolator(new AnticipateOvershootInterpolator(1.0f));
TransitionManager.beginDelayedTransition(mRootView, changeBounds);
mConstraintSet.applyTo(mRootView);
}
@Override
public void onBackPressed() {
if (mIsFilterVisible) {
showFilter(false);
mTxtCurrentTool.setText(R.string.app_name);
} else if (!mPhotoEditor.isCacheEmpty()) {
showSaveDialog();
} else {
super.onBackPressed();
}
}
}

View File

@ -18,15 +18,19 @@ import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@ -39,6 +43,7 @@ import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
@ -107,6 +112,7 @@ import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import app.fedilab.android.BuildConfig;
import app.fedilab.android.client.API;
import app.fedilab.android.client.APIResponse;
import app.fedilab.android.client.Entities.Account;
@ -154,6 +160,7 @@ import app.fedilab.android.interfaces.OnRetrieveAttachmentInterface;
import app.fedilab.android.interfaces.OnRetrieveEmojiInterface;
import app.fedilab.android.interfaces.OnRetrieveSearcAccountshInterface;
import app.fedilab.android.interfaces.OnRetrieveSearchInterface;
import static app.fedilab.android.helper.Helper.changeDrawableColor;
import static app.fedilab.android.helper.Helper.countWithEmoji;
@ -231,7 +238,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(getApplicationContext()));
final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
switch (theme){
switch (theme) {
case Helper.THEME_LIGHT:
setTheme(R.style.AppTheme);
break;
@ -246,21 +253,21 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
if (theme == Helper.THEME_DARK) {
style = R.style.DialogDark;
} else if (theme == Helper.THEME_BLACK){
} else if (theme == Helper.THEME_BLACK) {
style = R.style.DialogBlack;
}else {
} else {
style = R.style.Dialog;
}
filesMap = new HashMap<>();
if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA){
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) {
max_media_count = 9999;
}else{
} else {
max_media_count = 4;
}
autocomplete = false;
setContentView(R.layout.activity_toot);
ActionBar actionBar = getSupportActionBar();
if( actionBar != null ) {
if (actionBar != null) {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
assert inflater != null;
@SuppressLint("InflateParams") View view = inflater.inflate(R.layout.toot_action_bar, null);
@ -277,7 +284,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
finish();
}
});
if (theme == Helper.THEME_LIGHT){
if (theme == Helper.THEME_LIGHT) {
Toolbar toolbar = actionBar.getCustomView().findViewById(R.id.toolbar);
Helper.colorizeToolbar(toolbar, R.color.black, TootActivity.this);
}
@ -297,7 +304,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
Button toot_cw = findViewById(R.id.toot_cw);
toot_space_left = findViewById(R.id.toot_space_left);
toot_visibility = findViewById(R.id.toot_visibility);
if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA)
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA)
toot_visibility.setVisibility(View.GONE);
toot_picture = findViewById(R.id.toot_picture);
toot_picture_container = findViewById(R.id.toot_picture_container);
@ -311,7 +318,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
ImageButton toot_emoji = findViewById(R.id.toot_emoji);
poll_action = findViewById(R.id.poll_action);
isScheduled = false;
if( sharedpreferences.getBoolean(Helper.SET_DISPLAY_EMOJI, true)) {
if (sharedpreferences.getBoolean(Helper.SET_DISPLAY_EMOJI, true)) {
final EmojiPopup emojiPopup = EmojiPopup.Builder.fromRootView(drawer_layout).build(toot_content);
toot_emoji.setOnClickListener(new View.OnClickListener() {
@ -320,7 +327,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
emojiPopup.toggle(); // Toggles visibility of the Popup.
}
});
}else {
} else {
toot_emoji.setVisibility(View.GONE);
}
@ -334,7 +341,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
params.height = (int) Helper.convertDpToPixel(50, getApplicationContext());
params.width = (int) Helper.convertDpToPixel(50, getApplicationContext());
toot_picture_container.setLayoutParams(params);
}else {
} else {
ViewGroup.LayoutParams params = toot_picture_container.getLayoutParams();
params.height = (int) Helper.convertDpToPixel(100, getApplicationContext());
params.width = (int) Helper.convertDpToPixel(100, getApplicationContext());
@ -347,13 +354,13 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
ArrayList<Uri> sharedUri = new ArrayList<>();
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
restored = -1;
if(b != null) {
if (b != null) {
tootReply = b.getParcelable("tootReply");
scheduledstatus = b.getParcelable("storedStatus");
String accountReplyToken = b.getString("accountReplyToken", null);
accountReply = null;
if( accountReplyToken != null){
accountReply = new AccountDAO(getApplicationContext(),db).getAccountByToken(accountReplyToken);
if (accountReplyToken != null) {
accountReply = new AccountDAO(getApplicationContext(), db).getAccountByToken(accountReplyToken);
}
tootMention = b.getString("tootMention", null);
urlMention = b.getString("urlMention", null);
@ -362,7 +369,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
sharedContentIni = b.getString("sharedContent", null);
sharedSubject = b.getString("sharedSubject", null);
mentionAccount = b.getString("mentionAccount", null);
idRedirect = b.getParcelable("idRedirect");
idRedirect = b.getParcelable("idRedirect");
removed = b.getBoolean("removed");
visibility = b.getString("visibility", null);
restoredScheduled = b.getBoolean("restoredScheduled", false);
@ -374,7 +381,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
}
// ACTION_SEND_MULTIPLE route
else if( b.getInt("uriNumberMast", 0) > 1) {
else if (b.getInt("uriNumberMast", 0) > 1) {
ArrayList<Uri> fileUri = b.getParcelableArrayList("sharedUri");
if (fileUri != null) {
@ -383,42 +390,42 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
restored = b.getLong("restored", -1);
}
if( scheduledstatus != null)
if (scheduledstatus != null)
toot_it.setText(R.string.modify);
if(restoredScheduled){
if (restoredScheduled) {
toot_it.setVisibility(View.GONE);
invalidateOptionsMenu();
}
String userIdReply;
if( accountReply == null)
if (accountReply == null)
userIdReply = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
else
userIdReply = accountReply.getId();
if( accountReply == null)
account = new AccountDAO(getApplicationContext(),db).getAccountByID(userIdReply);
if (accountReply == null)
account = new AccountDAO(getApplicationContext(), db).getAccountByID(userIdReply);
else
account = accountReply;
if( MainActivity.social == null){
if (MainActivity.social == null) {
//Update the static variable which manages account type
if( account.getSocial() == null || account.getSocial().equals("MASTODON"))
if (account.getSocial() == null || account.getSocial().equals("MASTODON"))
MainActivity.social = UpdateAccountInfoAsyncTask.SOCIAL.MASTODON;
else if( account.getSocial().equals("PEERTUBE"))
else if (account.getSocial().equals("PEERTUBE"))
MainActivity.social = UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE;
else if( account.getSocial().equals("PIXELFED"))
else if (account.getSocial().equals("PIXELFED"))
MainActivity.social = UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED;
else if( account.getSocial().equals("PLEROMA"))
else if (account.getSocial().equals("PLEROMA"))
MainActivity.social = UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA;
else if( account.getSocial().equals("GNU"))
else if (account.getSocial().equals("GNU"))
MainActivity.social = UpdateAccountInfoAsyncTask.SOCIAL.GNU;
else if( account.getSocial().equals("FRIENDICA"))
else if (account.getSocial().equals("FRIENDICA"))
MainActivity.social = UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA;
}
switch (MainActivity.social){
switch (MainActivity.social) {
case GNU:
toot_it.setText(getText(R.string.queet_it));
break;
@ -432,18 +439,17 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
toot_it.setText(getText(R.string.toot_it));
}
if( tootReply != null) {
if (tootReply != null) {
tootReply();
}else {
if( title != null) {
if(MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU)
} else {
if (title != null) {
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU)
title.setText(getString(R.string.queet_title));
else
title.setText(getString(R.string.toot_title));
}
else {
if(MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU)
} else {
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU)
setTitle(R.string.queet_title);
else
setTitle(R.string.toot_title);
@ -451,12 +457,12 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
toot_content.requestFocus();
if( mentionAccount != null){
if (mentionAccount != null) {
toot_content.setText(String.format("@%s\n", mentionAccount));
toot_content.setSelection(toot_content.getText().length());
toot_space_left.setText(String.valueOf(countLength()));
}
if( tootMention != null && urlMention != null) {
if (tootMention != null && urlMention != null) {
if (fileMention != null) {
Bitmap pictureMention = BitmapFactory.decodeFile(getCacheDir() + "/" + fileMention);
AsyncTask.execute(new Runnable() {
@ -488,20 +494,19 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
initialContent = toot_content.getText().toString();
String url = account.getAvatar();
if( url.startsWith("/") ){
if (url.startsWith("/")) {
url = Helper.getLiveInstanceWithProtocol(getApplicationContext()) + account.getAvatar();
}
Helper.loadGiF(getApplicationContext(), url, pp_actionBar);
if( sharedContent != null ){ //Shared content
if (sharedContent != null) { //Shared content
if( sharedSubject != null){
if (sharedSubject != null) {
sharedContent = sharedSubject + "\n\n" + sharedContent;
}
if( b != null) {
if (b != null) {
final String image = b.getString("image");
String title = b.getString("title");
String description = b.getString("description");
@ -537,8 +542,8 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
if( tootReply == null) {
if( visibility == null) {
if (tootReply == null) {
if (visibility == null) {
String defaultVisibility = account.isLocked() ? "private" : "public";
visibility = sharedpreferences.getString(Helper.SET_TOOT_VISIBILITY + "@" + account.getAcct() + "@" + account.getInstance(), defaultVisibility);
}
@ -568,10 +573,10 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
toot_cw.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(toot_cw_content.getVisibility() == View.GONE) {
if (toot_cw_content.getVisibility() == View.GONE) {
toot_cw_content.setVisibility(View.VISIBLE);
toot_cw_content.requestFocus();
}else {
} else {
toot_cw_content.setVisibility(View.GONE);
toot_cw_content.setText("");
toot_content.requestFocus();
@ -593,7 +598,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
});
if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA)
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA)
toot_it.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
@ -602,7 +607,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
.inflate(R.menu.main_content_type, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
switch (item.getItemId()) {
case R.id.action_plain_text:
contentType = "text/plain";
break;
@ -648,14 +653,14 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
String[] mimetypes = {"image/*", "video/*"};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, PICK_IMAGE);
}else {
} else {
intent.setType("image/* video/*");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
Intent pickIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(intent, getString(R.string.toot_select_image));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{pickIntent});
startActivityForResult(chooserIntent, PICK_IMAGE);
}
@ -672,9 +677,13 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
toot_cw_content.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
toot_space_left.setText(String.valueOf(countLength()));
@ -788,15 +797,14 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
toot_space_left.setText(String.valueOf(totalChar));
}
};
if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA)
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA)
toot_content.addTextChangedListener(textWatcher);
if( scheduledstatus != null)
if (scheduledstatus != null)
restoreServerSchedule(scheduledstatus.getStatus());
if( restored != -1 ){
if (restored != -1) {
restoreToot(restored);
}
@ -808,11 +816,26 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
});
toot_space_left.setText(String.valueOf(countLength()));
LocalBroadcastManager.getInstance(this)
.registerReceiver(imageReceiver,
new IntentFilter(Helper.INTENT_SEND_MODIFIED_IMAGE));
}
private BroadcastReceiver imageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String imgpath = intent.getStringExtra("imgpath");
if( imgpath != null)
new asyncPicture(TootActivity.this, account, Uri.fromFile(new File(imgpath))).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
};
@Override
public void onDestroy(){
public void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(imageReceiver);
}
@ -831,7 +854,8 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
}
}
}
public void showAToast (String message){
public void showAToast(String message) {
if (mToast != null) {
mToast.cancel();
}
@ -844,7 +868,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
public void uploadSharedImage(ArrayList<Uri> uri) {
if (!uri.isEmpty()) {
int count = 0;
for(Uri fileUri: uri) {
for (Uri fileUri : uri) {
if (fileUri != null) {
if (count == max_media_count) {
break;
@ -855,12 +879,12 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
count++;
} catch (Exception e) {
e.printStackTrace();
Toasty.error(getApplicationContext(),getString(R.string.toot_select_image_error),Toast.LENGTH_LONG).show();
Toasty.error(getApplicationContext(), getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
toot_picture.setEnabled(true);
toot_it.setEnabled(true);
}
} else {
Toasty.error(getApplicationContext(),getString(R.string.toot_select_image_error),Toast.LENGTH_LONG).show();
Toasty.error(getApplicationContext(), getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
}
}
}
@ -878,12 +902,19 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
try {
photoFile = createImageFile();
} catch (IOException ignored) {
Toasty.error(getApplicationContext(),getString(R.string.toot_select_image_error),Toast.LENGTH_LONG).show();}
Toasty.error(getApplicationContext(), getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
photoFileUri = FileProvider.getUriForFile(this,
"app.fedilab.android.fileProvider",
photoFile);
if (!BuildConfig.DONATIONS) {
photoFileUri = FileProvider.getUriForFile(this,
"app.fedilab.android.fileProvider",
photoFile);
}else {
photoFileUri = FileProvider.getUriForFile(this,
"fr.gouv.etalab.mastodon.fileProvider",
photoFile);
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFileUri);
startActivityForResult(takePictureIntent, TAKE_PHOTO);
}
@ -909,19 +940,21 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
boolean photo_editor = sharedpreferences.getBoolean(Helper.SET_PHOTO_EDITOR, true);
if (requestCode == PICK_IMAGE && resultCode == RESULT_OK) {
picture_scrollview.setVisibility(View.VISIBLE);
if (data == null){
Toasty.error(getApplicationContext(),getString(R.string.toot_select_image_error),Toast.LENGTH_LONG).show();
if (data == null) {
Toasty.error(getApplicationContext(), getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return;
}
ClipData clipData = data.getClipData();
if (data.getData() == null && clipData == null) {
Toasty.error(getApplicationContext(),getString(R.string.toot_select_image_error),Toast.LENGTH_LONG).show();
Toasty.error(getApplicationContext(), getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return;
}
if( clipData != null ){
if (clipData != null) {
ArrayList<Uri> mArrayUri = new ArrayList<>();
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
@ -929,16 +962,24 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
mArrayUri.add(uri);
}
uploadSharedImage(mArrayUri);
}else{
} else {
try {
String filename = Helper.getFileName(TootActivity.this, data.getData());
String filename = Helper.getFileName(TootActivity.this, data.getData());
ContentResolver cr = getContentResolver();
String mime = cr.getType(data.getData());
if(mime != null && (mime.toLowerCase().contains("video") || mime.toLowerCase().contains("gif")) ) {
if (mime != null && (mime.toLowerCase().contains("video") || mime.toLowerCase().contains("gif"))) {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
new HttpsConnection(TootActivity.this, instance).upload(inputStream, filename, account, TootActivity.this);
} else if(mime != null && mime.toLowerCase().contains("image")) {
new asyncPicture(TootActivity.this, account, data.getData()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else if (mime != null && mime.toLowerCase().contains("image")) {
if( photo_editor) {
Intent intent = new Intent(TootActivity.this, PhotoEditorActivity.class);
Bundle b = new Bundle();
intent.putExtra("imageUri", data.getData().toString());
intent.putExtras(b);
startActivity(intent);
}else{
new asyncPicture(TootActivity.this, account, data.getData()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}else {
Toasty.error(getApplicationContext(),getString(R.string.toot_select_image_error),Toast.LENGTH_LONG).show();
}
@ -957,7 +998,15 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
toot_content.setSelection(toot_content.getText().length());
}
}else if (requestCode == TAKE_PHOTO && resultCode == RESULT_OK) {
new asyncPicture(TootActivity.this, account, photoFileUri).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
if( photo_editor) {
Intent intent = new Intent(TootActivity.this, PhotoEditorActivity.class);
Bundle b = new Bundle();
intent.putExtra("imageUri", photoFileUri.toString());
intent.putExtras(b);
startActivity(intent);
}else {
new asyncPicture(TootActivity.this, account, photoFileUri).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
}
@ -3065,7 +3114,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
int matchEnd = matcherALink.end();
final String url = content.substring(matcherALink.start(1), matcherALink.end(1));
if( matchEnd <= content.length() && matchEnd >= matchStart){
content = content.replaceFirst(url,"abcdefghijklmnopkrstuvw");
content = content.replaceAll(Pattern.quote(url),"abcdefghijklmnopkrstuvw");
}
}
}

View File

@ -819,7 +819,8 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s", statusId)), 60, null, prefKeyOauthTokenT);
Status status = parseStatuses(context, new JSONObject(response));
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new TimelineCacheDAO(context, db).update(status.getId(), response);
Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT);
new TimelineCacheDAO(context, db).update(status.getId(), response, account.getId(), account.getInstance());
statuses.add(status);
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
@ -1078,7 +1079,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/timelines/home"), 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response), true);
statuses = parseStatusesForCache(context, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException e) {
@ -2203,7 +2204,8 @@ public class API {
intentBC.putExtras(b);
LocalBroadcastManager.getInstance(context).sendBroadcast(intentBC);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new TimelineCacheDAO(context, db).update(targetedId, resp);
Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT);
new TimelineCacheDAO(context, db).update(targetedId, resp, account.getId(), account.getInstance());
}
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
@ -2366,8 +2368,9 @@ public class API {
intentBC.putExtras(b);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Status alreadyCached = new TimelineCacheDAO(context, db).getSingle(status.getId());
Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT);
if (alreadyCached != null) {
new TimelineCacheDAO(context, db).update(status.getId(), response);
new TimelineCacheDAO(context, db).update(status.getId(), response, account.getId(), account.getInstance());
}
LocalBroadcastManager.getInstance(context).sendBroadcast(intentBC);
return parsePoll(context, new JSONObject(response));
@ -3856,7 +3859,7 @@ public class API {
* @param jsonArray JSONArray
* @return List<Status>
*/
private static List<Status> parseStatuses(Context context, JSONArray jsonArray, boolean cached){
private List<Status> parseStatusesForCache(Context context, JSONArray jsonArray){
List<Status> statuses = new ArrayList<>();
try {
@ -3865,12 +3868,11 @@ public class API {
JSONObject resobj = jsonArray.getJSONObject(i);
Status status = parseStatuses(context, resobj);
if( cached) {
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Status alreadyCached = new TimelineCacheDAO(context, db).getSingle(status.getId());
if (alreadyCached == null) {
new TimelineCacheDAO(context, db).insert(status.getId(), resobj.toString());
}
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Status alreadyCached = new TimelineCacheDAO(context, db).getSingle(status.getId());
if (alreadyCached == null) {
Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT);
new TimelineCacheDAO(context, db).insert(status.getId(), resobj.toString(), account.getId(), account.getInstance());
}
i++;
statuses.add(status);

View File

@ -1395,7 +1395,8 @@ public class GNUAPI {
intentBC.putExtras(b);
LocalBroadcastManager.getInstance(context).sendBroadcast(intentBC);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new TimelineCacheDAO(context, db).update(targetedId, resp);
Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT);
new TimelineCacheDAO(context, db).update(targetedId, resp, account.getId(), account.getToken());
}else if( statusAction == API.StatusAction.UNSTATUS){
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
new TimelineCacheDAO(context, db).remove(targetedId);

View File

@ -464,6 +464,20 @@ public class SettingsFragment extends Fragment {
}
});
boolean photo_editor = sharedpreferences.getBoolean(Helper.SET_PHOTO_EDITOR, true);
final CheckBox set_photo_editor = rootView.findViewById(R.id.set_photo_editor);
set_photo_editor.setChecked(photo_editor);
set_photo_editor.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean(Helper.SET_PHOTO_EDITOR, set_photo_editor.isChecked());
editor.apply();
}
});
boolean remember_position_home = sharedpreferences.getBoolean(Helper.SET_REMEMBER_POSITION_HOME, true);
final CheckBox set_remember_position = rootView.findViewById(R.id.set_remember_position);
set_remember_position.setChecked(remember_position_home);

View File

@ -384,6 +384,7 @@ public class Helper {
public static final String SET_NOTIF_SILENT = "set_notif_silent";
public static final String SET_EXPAND_CW = "set_expand_cw";
public static final String SET_EXPAND_MEDIA = "set_expand_media";
public static final String SET_PHOTO_EDITOR = "set_photo_editor";
public static final String SET_DISPLAY_FOLLOW_INSTANCE = "set_display_follow_instance";
public static final String SET_DISPLAY_NEW_BADGE = "set_display_new_badge";
public static final String SET_DISPLAY_BOT_ICON = "set_display_bot_icon";
@ -408,6 +409,7 @@ public class Helper {
public static final String EP_AUTHORIZE = "/oauth/authorize";
//Proxy
public static final String SET_PROXY_ENABLED = "set_proxy_enabled";
public static final String SET_PROXY_TYPE = "set_proxy_type";
@ -427,6 +429,7 @@ public class Helper {
public static final String INTENT_ACTION = "intent_action";
public static final String INTENT_TARGETED_ACCOUNT = "intent_targeted_account";
public static final String INTENT_BACKUP_FINISH = "intent_backup_finish";
public static final String INTENT_SEND_MODIFIED_IMAGE = "intent_send_modified_image";
//Receiver
public static final String RECEIVE_DATA = "receive_data";
public static final String RECEIVE_ACTION = "receive_action";

View File

@ -0,0 +1,123 @@
package app.fedilab.android.imageeditor;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.android.R;
/**
* Created by Ahmed Adel on 5/8/17.
*/
public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.ViewHolder> {
private Context context;
private LayoutInflater inflater;
private List<Integer> colorPickerColors;
private OnColorPickerClickListener onColorPickerClickListener;
ColorPickerAdapter(@NonNull Context context, @NonNull List<Integer> colorPickerColors) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.colorPickerColors = colorPickerColors;
}
ColorPickerAdapter(@NonNull Context context) {
this(context, getDefaultColors(context));
this.context = context;
this.inflater = LayoutInflater.from(context);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.color_picker_item_list, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.colorPickerView.setBackgroundColor(colorPickerColors.get(position));
}
@Override
public int getItemCount() {
return colorPickerColors.size();
}
private void buildColorPickerView(View view, int colorCode) {
view.setVisibility(View.VISIBLE);
ShapeDrawable biggerCircle = new ShapeDrawable(new OvalShape());
biggerCircle.setIntrinsicHeight(20);
biggerCircle.setIntrinsicWidth(20);
biggerCircle.setBounds(new Rect(0, 0, 20, 20));
biggerCircle.getPaint().setColor(colorCode);
ShapeDrawable smallerCircle = new ShapeDrawable(new OvalShape());
smallerCircle.setIntrinsicHeight(5);
smallerCircle.setIntrinsicWidth(5);
smallerCircle.setBounds(new Rect(0, 0, 5, 5));
smallerCircle.getPaint().setColor(Color.WHITE);
smallerCircle.setPadding(10, 10, 10, 10);
Drawable[] drawables = {smallerCircle, biggerCircle};
LayerDrawable layerDrawable = new LayerDrawable(drawables);
view.setBackgroundDrawable(layerDrawable);
}
public void setOnColorPickerClickListener(OnColorPickerClickListener onColorPickerClickListener) {
this.onColorPickerClickListener = onColorPickerClickListener;
}
class ViewHolder extends RecyclerView.ViewHolder {
View colorPickerView;
public ViewHolder(View itemView) {
super(itemView);
colorPickerView = itemView.findViewById(R.id.color_picker_view);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onColorPickerClickListener != null)
onColorPickerClickListener.onColorPickerClickListener(colorPickerColors.get(getAdapterPosition()));
}
});
}
}
public interface OnColorPickerClickListener {
void onColorPickerClickListener(int colorCode);
}
public static List<Integer> getDefaultColors(Context context) {
ArrayList<Integer> colorPickerColors = new ArrayList<>();
colorPickerColors.add(ContextCompat.getColor(context, R.color.blue_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.brown_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.green_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.orange_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.red_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.black));
colorPickerColors.add(ContextCompat.getColor(context, R.color.red_orange_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.sky_blue_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.violet_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.white));
colorPickerColors.add(ContextCompat.getColor(context, R.color.yellow_color_picker));
colorPickerColors.add(ContextCompat.getColor(context, R.color.yellow_green_color_picker));
return colorPickerColors;
}
}

View File

@ -0,0 +1,116 @@
package app.fedilab.android.imageeditor;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialogFragment;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import app.fedilab.android.R;
import ja.burhanrashid52.photoeditor.PhotoEditor;
public class EmojiBSFragment extends BottomSheetDialogFragment {
public EmojiBSFragment() {
// Required empty public constructor
}
private EmojiListener mEmojiListener;
public interface EmojiListener {
void onEmojiClick(String emojiUnicode);
}
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
@SuppressLint("RestrictedApi")
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(), R.layout.fragment_bottom_sticker_emoji_dialog, null);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
if (behavior instanceof BottomSheetBehavior) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
}
((View) contentView.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
RecyclerView rvEmoji = contentView.findViewById(R.id.rvEmoji);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 5);
rvEmoji.setLayoutManager(gridLayoutManager);
EmojiAdapter emojiAdapter = new EmojiAdapter();
rvEmoji.setAdapter(emojiAdapter);
}
public void setEmojiListener(EmojiListener emojiListener) {
mEmojiListener = emojiListener;
}
public class EmojiAdapter extends RecyclerView.Adapter<EmojiAdapter.ViewHolder> {
ArrayList<String> emojisList = PhotoEditor.getEmojis(getActivity());
@NotNull
@Override
public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_emoji, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NotNull ViewHolder holder, int position) {
holder.txtEmoji.setText(emojisList.get(position));
}
@Override
public int getItemCount() {
return emojisList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView txtEmoji;
ViewHolder(View itemView) {
super(itemView);
txtEmoji = itemView.findViewById(R.id.txtEmoji);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mEmojiListener != null) {
mEmojiListener.onEmojiClick(emojisList.get(getLayoutPosition()));
}
dismiss();
}
});
}
}
}
}

View File

@ -0,0 +1,101 @@
package app.fedilab.android.imageeditor;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetDialogFragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SeekBar;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import app.fedilab.android.R;
public class PropertiesBSFragment extends BottomSheetDialogFragment implements SeekBar.OnSeekBarChangeListener {
public PropertiesBSFragment() {
// Required empty public constructor
}
private Properties mProperties;
public interface Properties {
void onColorChanged(int colorCode);
void onOpacityChanged(int opacity);
void onBrushSizeChanged(int brushSize);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_bottom_properties_dialog, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecyclerView rvColor = view.findViewById(R.id.rvColors);
SeekBar sbOpacity = view.findViewById(R.id.sbOpacity);
SeekBar sbBrushSize = view.findViewById(R.id.sbSize);
sbOpacity.setOnSeekBarChangeListener(this);
sbBrushSize.setOnSeekBarChangeListener(this);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
rvColor.setLayoutManager(layoutManager);
rvColor.setHasFixedSize(true);
ColorPickerAdapter colorPickerAdapter = new ColorPickerAdapter(Objects.requireNonNull(getActivity()));
colorPickerAdapter.setOnColorPickerClickListener(new ColorPickerAdapter.OnColorPickerClickListener() {
@Override
public void onColorPickerClickListener(int colorCode) {
if (mProperties != null) {
dismiss();
mProperties.onColorChanged(colorCode);
}
}
});
rvColor.setAdapter(colorPickerAdapter);
}
public void setPropertiesChangeListener(Properties properties) {
mProperties = properties;
}
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
switch (seekBar.getId()) {
case R.id.sbOpacity:
if (mProperties != null) {
mProperties.onOpacityChanged(i);
}
break;
case R.id.sbSize:
if (mProperties != null) {
mProperties.onBrushSizeChanged(i);
}
break;
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}

View File

@ -0,0 +1,154 @@
package app.fedilab.android.imageeditor;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialogFragment;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import org.jetbrains.annotations.NotNull;
import app.fedilab.android.R;
public class StickerBSFragment extends BottomSheetDialogFragment {
public StickerBSFragment() {
// Required empty public constructor
}
private StickerListener mStickerListener;
public void setStickerListener(StickerListener stickerListener) {
mStickerListener = stickerListener;
}
public interface StickerListener {
void onStickerClick(Bitmap bitmap);
}
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
@SuppressLint("RestrictedApi")
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(), R.layout.fragment_bottom_sticker_emoji_dialog, null);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
if (behavior instanceof BottomSheetBehavior) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
}
((View) contentView.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
RecyclerView rvEmoji = contentView.findViewById(R.id.rvEmoji);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 3);
rvEmoji.setLayoutManager(gridLayoutManager);
StickerAdapter stickerAdapter = new StickerAdapter();
rvEmoji.setAdapter(stickerAdapter);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
public class StickerAdapter extends RecyclerView.Adapter<StickerAdapter.ViewHolder> {
int[] stickerList = new int[]{
R.drawable.bubble1,
R.drawable.cat1,
R.drawable.cat2,
R.drawable.cat3,
R.drawable.cat4,
R.drawable.cat5,
R.drawable.dog1,
R.drawable.dog2,
R.drawable.flower1,
R.drawable.flower2,
R.drawable.sun,
R.drawable.tux1,
};
@NotNull
@Override
public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_sticker, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NotNull ViewHolder holder, int position) {
holder.imgSticker.setImageResource(stickerList[position]);
}
@Override
public int getItemCount() {
return stickerList.length;
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView imgSticker;
ViewHolder(View itemView) {
super(itemView);
imgSticker = itemView.findViewById(R.id.imgSticker);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mStickerListener != null) {
mStickerListener.onStickerClick(
BitmapFactory.decodeResource(getResources(),
stickerList[getLayoutPosition()]));
}
dismiss();
}
});
}
}
}
private String convertEmoji(String emoji) {
String returnedEmoji = "";
try {
int convertEmojiToInt = Integer.parseInt(emoji.substring(2), 16);
returnedEmoji = getEmojiByUnicode(convertEmojiToInt);
} catch (NumberFormatException e) {
returnedEmoji = "";
}
return returnedEmoji;
}
private String getEmojiByUnicode(int unicode) {
return new String(Character.toChars(unicode));
}
}

View File

@ -0,0 +1,132 @@
package app.fedilab.android.imageeditor;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import org.jetbrains.annotations.NotNull;
import app.fedilab.android.R;
/**
* Created by Burhanuddin Rashid on 1/16/2018.
*/
public class TextEditorDialogFragment extends DialogFragment {
public static final String TAG = TextEditorDialogFragment.class.getSimpleName();
public static final String EXTRA_INPUT_TEXT = "extra_input_text";
public static final String EXTRA_COLOR_CODE = "extra_color_code";
private EditText mAddTextEditText;
private TextView mAddTextDoneTextView;
private InputMethodManager mInputMethodManager;
private int mColorCode;
private TextEditor mTextEditor;
public interface TextEditor {
void onDone(String inputText, int colorCode);
}
//Show dialog with provide text and text color
public static TextEditorDialogFragment show(@NonNull AppCompatActivity appCompatActivity,
@NonNull String inputText,
@ColorInt int colorCode) {
Bundle args = new Bundle();
args.putString(EXTRA_INPUT_TEXT, inputText);
args.putInt(EXTRA_COLOR_CODE, colorCode);
TextEditorDialogFragment fragment = new TextEditorDialogFragment();
fragment.setArguments(args);
fragment.show(appCompatActivity.getSupportFragmentManager(), TAG);
return fragment;
}
//Show dialog with default text input as empty and text color white
public static TextEditorDialogFragment show(@NonNull AppCompatActivity appCompatActivity) {
return show(appCompatActivity,
"", ContextCompat.getColor(appCompatActivity, R.color.white));
}
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
//Make dialog full screen with transparent background
if (dialog != null) {
int width = ViewGroup.LayoutParams.MATCH_PARENT;
int height = ViewGroup.LayoutParams.MATCH_PARENT;
dialog.getWindow().setLayout(width, height);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
}
}
@Nullable
@Override
public View onCreateView(@NotNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.add_text_dialog, container, false);
}
@Override
public void onViewCreated(@NotNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAddTextEditText = view.findViewById(R.id.add_text_edit_text);
mInputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
mAddTextDoneTextView = view.findViewById(R.id.add_text_done_tv);
//Setup the color picker for text color
RecyclerView addTextColorPickerRecyclerView = view.findViewById(R.id.add_text_color_picker_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
addTextColorPickerRecyclerView.setLayoutManager(layoutManager);
addTextColorPickerRecyclerView.setHasFixedSize(true);
ColorPickerAdapter colorPickerAdapter = new ColorPickerAdapter(getActivity());
//This listener will change the text color when clicked on any color from picker
colorPickerAdapter.setOnColorPickerClickListener(new ColorPickerAdapter.OnColorPickerClickListener() {
@Override
public void onColorPickerClickListener(int colorCode) {
mColorCode = colorCode;
mAddTextEditText.setTextColor(colorCode);
}
});
addTextColorPickerRecyclerView.setAdapter(colorPickerAdapter);
mAddTextEditText.setText(getArguments().getString(EXTRA_INPUT_TEXT));
mColorCode = getArguments().getInt(EXTRA_COLOR_CODE);
mAddTextEditText.setTextColor(mColorCode);
mInputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
//Make a callback on activity when user is done with text editing
mAddTextDoneTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mInputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
dismiss();
String inputText = mAddTextEditText.getText().toString();
if (!TextUtils.isEmpty(inputText) && mTextEditor != null) {
mTextEditor.onDone(inputText, mColorCode);
}
}
});
}
//Callback to listener if user is done with text editing
public void setOnTextEditorListener(TextEditor textEditor) {
mTextEditor = textEditor;
}
}

View File

@ -0,0 +1,7 @@
package app.fedilab.android.imageeditor.filters;
import ja.burhanrashid52.photoeditor.PhotoFilter;
public interface FilterListener {
void onFilterSelected(PhotoFilter photoFilter);
}

View File

@ -0,0 +1,115 @@
package app.fedilab.android.imageeditor.filters;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.android.R;
import ja.burhanrashid52.photoeditor.PhotoFilter;
/**
* @author <a href="https://github.com/burhanrashid52">Burhanuddin Rashid</a>
* @version 0.1.2
* @since 5/23/2018
*/
public class FilterViewAdapter extends RecyclerView.Adapter<FilterViewAdapter.ViewHolder> {
private FilterListener mFilterListener;
private List<Pair<String, PhotoFilter>> mPairList = new ArrayList<>();
public FilterViewAdapter(FilterListener filterListener) {
mFilterListener = filterListener;
setupFilters();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_filter_view, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Pair<String, PhotoFilter> filterPair = mPairList.get(position);
Bitmap fromAsset = getBitmapFromAsset(holder.itemView.getContext(), filterPair.first);
holder.mImageFilterView.setImageBitmap(fromAsset);
holder.mTxtFilterName.setText(filterPair.second.name().replace("_", " "));
}
@Override
public int getItemCount() {
return mPairList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView mImageFilterView;
TextView mTxtFilterName;
ViewHolder(View itemView) {
super(itemView);
mImageFilterView = itemView.findViewById(R.id.imgFilterView);
mTxtFilterName = itemView.findViewById(R.id.txtFilterName);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFilterListener.onFilterSelected(mPairList.get(getLayoutPosition()).second);
}
});
}
}
private Bitmap getBitmapFromAsset(Context context, String strName) {
AssetManager assetManager = context.getAssets();
InputStream istr = null;
try {
istr = assetManager.open(strName);
return BitmapFactory.decodeStream(istr);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private void setupFilters() {
mPairList.add(new Pair<>("filters/original.jpg", PhotoFilter.NONE));
mPairList.add(new Pair<>("filters/auto_fix.png", PhotoFilter.AUTO_FIX));
mPairList.add(new Pair<>("filters/brightness.png", PhotoFilter.BRIGHTNESS));
mPairList.add(new Pair<>("filters/contrast.png", PhotoFilter.CONTRAST));
mPairList.add(new Pair<>("filters/documentary.png", PhotoFilter.DOCUMENTARY));
mPairList.add(new Pair<>("filters/dual_tone.png", PhotoFilter.DUE_TONE));
mPairList.add(new Pair<>("filters/fill_light.png", PhotoFilter.FILL_LIGHT));
mPairList.add(new Pair<>("filters/fish_eye.png", PhotoFilter.FISH_EYE));
mPairList.add(new Pair<>("filters/grain.png", PhotoFilter.GRAIN));
mPairList.add(new Pair<>("filters/gray_scale.png", PhotoFilter.GRAY_SCALE));
mPairList.add(new Pair<>("filters/lomish.png", PhotoFilter.LOMISH));
mPairList.add(new Pair<>("filters/negative.png", PhotoFilter.NEGATIVE));
mPairList.add(new Pair<>("filters/posterize.png", PhotoFilter.POSTERIZE));
mPairList.add(new Pair<>("filters/saturate.png", PhotoFilter.SATURATE));
mPairList.add(new Pair<>("filters/sepia.png", PhotoFilter.SEPIA));
mPairList.add(new Pair<>("filters/sharpen.png", PhotoFilter.SHARPEN));
mPairList.add(new Pair<>("filters/temprature.png", PhotoFilter.TEMPERATURE));
mPairList.add(new Pair<>("filters/tint.png", PhotoFilter.TINT));
mPairList.add(new Pair<>("filters/vignette.png", PhotoFilter.VIGNETTE));
mPairList.add(new Pair<>("filters/cross_process.png", PhotoFilter.CROSS_PROCESS));
mPairList.add(new Pair<>("filters/b_n_w.png", PhotoFilter.BLACK_WHITE));
mPairList.add(new Pair<>("filters/flip_horizental.png", PhotoFilter.FLIP_HORIZONTAL));
mPairList.add(new Pair<>("filters/flip_vertical.png", PhotoFilter.FLIP_VERTICAL));
mPairList.add(new Pair<>("filters/rotate.png", PhotoFilter.ROTATE));
}
}

View File

@ -0,0 +1,91 @@
package app.fedilab.android.imageeditor.tools;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.android.R;
/**
* @author <a href="https://github.com/burhanrashid52">Burhanuddin Rashid</a>
* @version 0.1.2
* @since 5/23/2018
*/
public class EditingToolsAdapter extends RecyclerView.Adapter<EditingToolsAdapter.ViewHolder> {
private List<ToolModel> mToolList = new ArrayList<>();
private OnItemSelected mOnItemSelected;
public EditingToolsAdapter(OnItemSelected onItemSelected) {
mOnItemSelected = onItemSelected;
mToolList.add(new ToolModel("Brush", R.drawable.ic_brush_edit, ToolType.BRUSH));
mToolList.add(new ToolModel("Text", R.drawable.ic_text, ToolType.TEXT));
// mToolList.add(new ToolModel("Eraser", R.drawable.ic_eraser, ToolType.ERASER));
mToolList.add(new ToolModel("Filter", R.drawable.ic_photo_filter, ToolType.FILTER));
mToolList.add(new ToolModel("Crop", R.drawable.ic_crop, ToolType.CROP));
mToolList.add(new ToolModel("Emoji", R.drawable.ic_insert_emoticon_media, ToolType.EMOJI));
mToolList.add(new ToolModel("Sticker", R.drawable.ic_sticker, ToolType.STICKER));
}
public interface OnItemSelected {
void onToolSelected(ToolType toolType);
}
class ToolModel {
private String mToolName;
private int mToolIcon;
private ToolType mToolType;
ToolModel(String toolName, int toolIcon, ToolType toolType) {
mToolName = toolName;
mToolIcon = toolIcon;
mToolType = toolType;
}
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_editing_tools, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ToolModel item = mToolList.get(position);
holder.txtTool.setText(item.mToolName);
holder.imgToolIcon.setImageResource(item.mToolIcon);
}
@Override
public int getItemCount() {
return mToolList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView imgToolIcon;
TextView txtTool;
ViewHolder(View itemView) {
super(itemView);
imgToolIcon = itemView.findViewById(R.id.imgToolIcon);
txtTool = itemView.findViewById(R.id.txtTool);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemSelected.onToolSelected(mToolList.get(getLayoutPosition()).mToolType);
}
});
}
}
}

View File

@ -0,0 +1,16 @@
package app.fedilab.android.imageeditor.tools;
/**
* @author <a href="https://github.com/burhanrashid52">Burhanuddin Rashid</a>
* @version 0.1.2
* @since 5/23/2018
*/
public enum ToolType {
BRUSH,
TEXT,
ERASER,
FILTER,
EMOJI,
STICKER,
CROP
}

View File

@ -53,10 +53,7 @@ public class TimelineCacheDAO {
* Insert a status in database
* @return boolean
*/
public long insert(String statusId, String jsonString) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(context);
public long insert(String statusId, String jsonString, String userId, String instance) {
ContentValues values = new ContentValues();
values.put(Sqlite.COL_INSTANCE, instance);
values.put(Sqlite.COL_STATUS_ID, statusId);
@ -78,10 +75,7 @@ public class TimelineCacheDAO {
/**
* Update a status in database
*/
public void update(String statusId, String jsonString) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(context);
public void update(String statusId, String jsonString, String userId, String instance) {
ContentValues values = new ContentValues();
values.put(Sqlite.COL_DATE, Helper.dateToString(new Date()));
values.put(Sqlite.COL_CACHE, jsonString);

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M7,14c-1.66,0 -3,1.34 -3,3 0,1.31 -1.16,2 -2,2 0.92,1.22 2.49,2 4,2 2.21,0 4,-1.79 4,-4 0,-1.66 -1.34,-3 -3,-3zM20.71,4.63l-1.34,-1.34c-0.39,-0.39 -1.02,-0.39 -1.41,0L9,12.25 11.75,15l8.96,-8.96c0.39,-0.39 0.39,-1.02 0,-1.41z"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path
android:fillColor="#606984"
android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M17,15h2V7c0,-1.1 -0.9,-2 -2,-2H9v2h8v8zM7,17V1H5v4H1v2h4v10c0,1.1 0.9,2 2,2h10v4h2v-4h4v-2H7z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM15.5,11c0.83,0 1.5,-0.67 1.5,-1.5S16.33,8 15.5,8 14,8.67 14,9.5s0.67,1.5 1.5,1.5zM8.5,11c0.83,0 1.5,-0.67 1.5,-1.5S9.33,8 8.5,8 7,8.67 7,9.5 7.67,11 8.5,11zM12,17.5c2.33,0 4.31,-1.46 5.11,-3.5L6.89,14c0.8,2.04 2.78,3.5 5.11,3.5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M19.02,10v9L5,19L5,5h9L14,3L5.02,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-9h-2zM17,10l0.94,-2.06L20,7l-2.06,-0.94L17,4l-0.94,2.06L14,7l2.06,0.94zM13.25,10.75L12,8l-1.25,2.75L8,12l2.75,1.25L12,16l1.25,-2.75L16,12z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M18.4,10.6C16.55,8.99 14.15,8 11.5,8c-4.65,0 -8.58,3.03 -9.96,7.22L3.9,16c1.05,-3.19 4.05,-5.5 7.6,-5.5 1.95,0 3.73,0.72 5.12,1.88L13,16h9V7l-3.6,3.6z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M17.63,5.84C17.27,5.33 16.67,5 16,5L5,5.01C3.9,5.01 3,5.9 3,7v10c0,1.1 0.9,1.99 2,1.99L16,19c0.67,0 1.27,-0.33 1.63,-0.84L22,12l-4.37,-6.16z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M2.5,4v3h5v12h3L10.5,7h5L15.5,4h-13zM21.5,9h-9v3h3v7h3v-7h3L21.5,9z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#606984"
android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z"/>
</vector>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="2dp"
android:color="#FFFFFF" />
<padding
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp" />
<corners android:radius="50dp" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -432,12 +432,21 @@
android:text="@string/set_forward_tags"
android:layout_height="wrap_content" />
<EditText
android:hint="@string/settings_custom_sharing_url"
android:id="@+id/custom_sharing_url"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/set_photo_editor"
android:layout_width="wrap_content"
android:layout_marginTop="@dimen/settings_checkbox_margin"
android:layout_marginBottom="@dimen/settings_checkbox_margin"
android:text="@string/set_photo_editor"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Thomas Schneider
This file is a part of Fedilab
This program is free software; you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation; either version 3 of the
License, or (at your option) any later version.
Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along with Fedilab; if not,
see <http://www.gnu.org/licenses>.
-->
<android.support.constraint.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_end="?attr/actionBarSize" />
<ja.burhanrashid52.photoeditor.PhotoEditorView
android:id="@+id/photoEditorView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<ImageView
android:id="@+id/imgUndo"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:padding="8dp"
android:src="@drawable/ic_undo"
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
app:layout_constraintEnd_toStartOf="@+id/imgRedo"
android:contentDescription="@string/undo" />
<ImageView
android:id="@+id/imgRedo"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:padding="8dp"
android:src="@drawable/ic_redo"
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
app:layout_constraintEnd_toEndOf="parent"
android:contentDescription="@string/redo" />
<ImageView
android:id="@+id/imgGallery"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:padding="8dp"
android:src="@drawable/ic_gallery"
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
app:layout_constraintStart_toStartOf="parent"
android:contentDescription="@string/gallery"/>
<ImageView
android:id="@+id/imgCamera"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:padding="8dp"
android:src="@drawable/ic_camera"
app:layout_constraintBottom_toTopOf="@+id/rvConstraintTools"
app:layout_constraintStart_toEndOf="@id/imgGallery"
android:contentDescription="@string/camera"
/>
<ImageView
android:id="@+id/imgClose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_margin="8dp"
android:src="@drawable/ic_close"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:contentDescription="@string/close"
app:layout_constraintTop_toBottomOf="@+id/guideline" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rvConstraintTools"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="4dp"
android:paddingTop="4dp"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@+id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:listitem="@layout/row_editing_tools" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rvFilterView"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="@+id/rvConstraintTools"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/rvConstraintTools"
tools:listitem="@layout/row_filter_view" />
<TextView
android:id="@+id/txtCurrentTool"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:singleLine="true"
android:text="@string/app_name"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/guideline" />
<Button
android:id="@+id/send"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="end"
android:gravity="center"
android:padding="0dp"
android:layout_margin="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/imgSave"
app:layout_constraintTop_toBottomOf="@+id/guideline"
android:text="@string/validate" />
<ImageView
android:id="@+id/imgSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:src="@drawable/ic_save_gallery"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:contentDescription="@string/save"
app:layout_constraintTop_toBottomOf="@+id/guideline" />
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#B3000000"
android:orientation="vertical">
<TextView
android:id="@+id/add_text_done_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="20dp"
android:background="@drawable/rounded_border_text_view"
android:padding="10dp"
android:text="@string/done"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="15sp" />
<EditText
android:id="@+id/add_text_edit_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/add_text_color_picker_relative_layout"
android:layout_below="@+id/add_text_done_tv"
android:background="@null"
android:gravity="center"
android:inputType="textMultiLine"
android:textSize="40sp" />
<RelativeLayout
android:id="@+id/add_text_color_picker_relative_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<android.support.v7.widget.RecyclerView
android:id="@+id/add_text_color_picker_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:background="@android:color/black"
tools:listitem="@layout/color_picker_item_list" />
</RelativeLayout>
</RelativeLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View
android:id="@+id/color_picker_view"
android:layout_width="40dp"
android:layout_height="50dp"
android:layout_alignParentTop="true"
android:background="@android:color/white"
tools:text="" />
</RelativeLayout>

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/black"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/rvColors"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:orientation="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sbOpacity"
tools:listitem="@layout/color_picker_item_list"
android:layout_alignParentRight="true" />
<SeekBar
android:id="@+id/sbOpacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:progress="100"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtOpacity" />
<TextView
android:id="@+id/txtOpacity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:text="@string/opacity"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sbSize" />
<SeekBar
android:id="@+id/sbSize"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:progress="25"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtBrushSize" />
<TextView
android:id="@+id/txtBrushSize"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="@string/label_brush"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp">
<TextView
android:id="@+id/txtClose"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_marginStart="8dp"
android:gravity="center"
android:text="@string/close"
android:textAppearance="@style/TextAppearance.AppCompat.Large.Inverse"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginLeft="8dp" />
<View
android:id="@+id/lineView"
android:layout_width="match_parent"
android:layout_height="2px"
android:background="@android:color/white"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/txtClose"
tools:ignore="PxUsage" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rvEmoji"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_behavior="@string/bottom_sheet_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lineView" />
<TextView
android:id="@+id/txtDone"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_marginEnd="8dp"
android:gravity="center"
android:text="@string/done"
android:textAppearance="@style/TextAppearance.AppCompat.Large.Inverse"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginRight="8dp" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>

View File

@ -443,6 +443,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/set_photo_editor"
android:layout_width="wrap_content"
android:layout_marginTop="@dimen/settings_checkbox_margin"
android:layout_marginBottom="@dimen/settings_checkbox_margin"
android:text="@string/set_photo_editor"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Thomas Schneider
This file is a part of Fedilab
This program is free software; you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation; either version 3 of the
License, or (at your option) any later version.
Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along with Fedilab; if not,
see <http://www.gnu.org/licenses>.
-->
<ja.burhanrashid52.photoeditor.PhotoEditorView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/photoEditorView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:padding="4dp"
tools:background="@android:color/black">
<ImageView
android:id="@+id/imgToolIcon"
android:layout_width="@dimen/editor_size"
android:layout_height="@dimen/editor_size"
android:layout_margin="4dp"
android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:src="@drawable/ic_brush_edit"
android:contentDescription="@string/label_brush" />
<TextView
android:id="@+id/txtTool"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imgToolIcon"
tools:text="@string/label_brush" />
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtEmoji"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:padding="2dp"
android:textColor="#FFFFFF"
android:textSize="35sp"
tools:android="Burhanuddin" />
</LinearLayout>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="2dp">
<ImageView
android:id="@+id/imgFilterView"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@tools:sample/backgrounds/scenic" />
<TextView
android:id="@+id/txtFilterName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#606984"
android:gravity="center"
android:padding="4dp"
android:textColor="@android:color/white"
android:textSize="8sp"
app:layout_constraintBottom_toBottomOf="@+id/imgFilterView"
app:layout_constraintEnd_toEndOf="@+id/imgFilterView"
app:layout_constraintStart_toStartOf="@+id/imgFilterView"
tools:text="@tools:sample/full_names" />
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp">
<ImageView
android:id="@+id/imgSticker"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

View File

@ -856,6 +856,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -858,7 +858,7 @@
<string name="set_blur_sensitive">تعتيم الوسائط الحساسة</string>
<string name="set_display_timeline_in_list">عرض الخيوط الزمنية في قائمة</string>
<string name="display_timeline">عرض الخيوط الزمنية</string>
<string name="set_display_bot_icon">Mark bot accounts in toots</string>
<string name="set_display_bot_icon">ضع إشارة على حسابات الروبوتات في التبويقات</string>
<string name="add_tags">إدارة الوسوم</string>
<string name="set_remember_position">تذكّر وضعيتي على الخيط الرئيسي</string>
<string name="history">التاريخ</string>
@ -871,6 +871,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">إنشاء قائمة تشغيل</string>
<string name="action_playlist_empty_content">قائمة التشغيل هذه فارغة حاليا.</string>
<string name="edit_media">تحرير الوسائط</string>
<string name="redo">إعادة</string>
<string name="gallery">المعرض</string>
<string name="label_emoji">إيموجي</string>
<string name="label_sticker">ملصق</string>
<string name="label_eraser">مِمْحاة</string>
<string name="label_text">نص</string>
<string name="label_filter">فلتر</string>
<string name="label_adjust">ضبط</string>
<string name="label_brush">فرشاة</string>
<string name="confirm_exit_editing">هل أنت متأكد من الخروج دون حفظ الصورة؟</string>
<string name="discard">تجاهل</string>
<string name="saving">جاري الحفظ…</string>
<string name="image_saved">تم حفظ الصورة بنجاح!</string>
<string name="save_image_failed">فشل في حفظ الصورة</string>
<string name="opacity">الشفافيّة</string>
<string name="label_crop">اقتصاص</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="zero">لا صوت</item>
<item quantity="one">صوت واحد</item>

View File

@ -838,16 +838,34 @@ Quan s\'esborra l\'aplicació s\'eliminen les dades immediatament.\n
<string name="set_display_bot_icon">Marcar els brams fets per bots</string>
<string name="add_tags">Gestionar etiquetes</string>
<string name="set_remember_position">Recordar la posició en la pissarra principal</string>
<string name="history">History</string>
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="privacy">Privacy</string>
<string name="create">Create</string>
<string name="action_playlist_add">You don\'t have any playlists. Click on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="history">Historial</string>
<string name="playlists">Llistes de reproducció</string>
<string name="display_name">Nom que es mostrarà</string>
<string name="privacy">Privacitat</string>
<string name="create">Crea</string>
<string name="action_playlist_add">No tens llistes de reproducció. Clica la icona \"+\" per afegir-ne de noves</string>
<string name="error_display_name">Cal que et mostris amb algun nom!</string>
<string name="error_channel_mandatory">Aquest canal és obligat quan la llista és pública.</string>
<string name="action_playlist_create">Crea una llista de reproducció</string>
<string name="action_playlist_empty_content">La llista encara és buida.</string>
<string name="edit_media">Editar document multimèdia</string>
<string name="redo">tornar-hi</string>
<string name="gallery">Galeria</string>
<string name="label_emoji">Emoticones</string>
<string name="label_sticker">Enganxina</string>
<string name="label_eraser">Goma d\'esborrar</string>
<string name="label_text">Text</string>
<string name="label_filter">Filtre</string>
<string name="label_adjust">Ajustar</string>
<string name="label_brush">Pinzell</string>
<string name="confirm_exit_editing">Esteu segur per sortir sense desar la imatge?</string>
<string name="discard">Descarta</string>
<string name="saving">Desant…</string>
<string name="image_saved">Imatge desada amb èxit!</string>
<string name="save_image_failed">No s\'ha pogut desar la imatge</string>
<string name="opacity">Opacitat</string>
<string name="label_crop">Retalla</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vot</item>
<item quantity="other">%d vots</item>

View File

@ -861,6 +861,24 @@ Uživatelské jméno a heslo nejsou nikdy ukládány. Jsou použity pouze během
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d hlas</item>
<item quantity="few">%d hlasy</item>

View File

@ -871,6 +871,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="zero">%d votes</item>
<item quantity="one">%d vote</item>

View File

@ -856,6 +856,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -836,17 +836,35 @@ Sobald Sie die ersten Buchstaben eintippen, werden Namensvorschläge angezeigt\n
<string name="display_timeline">Zeitleisten anzeigen</string>
<string name="set_display_bot_icon">Toots von Bot-Konten kennzeichnen</string>
<string name="add_tags">Schlagwörter verwalten</string>
<string name="set_remember_position">Position der Startseiten-Zeitleiste merken</string>
<string name="set_remember_position">Position innerhalb der Startleiste merken</string>
<string name="history">Verlauf</string>
<string name="playlists">Wiedergabelisten</string>
<string name="display_name">Anzeigenamen</string>
<string name="display_name">Anzeigename</string>
<string name="privacy">Datenschutz</string>
<string name="create">Erstellen</string>
<string name="action_playlist_add">Sie haben noch keine Wiedergabelisten. Klicken Sie auf das Symbol „➕”, um eine neue Wiedergabeliste hinzuzufügen.</string>
<string name="error_display_name">Sie müssen einen Anzeigenamen angeben!</string>
<string name="error_channel_mandatory">Der Kanal wird benötigt, wenn es sich um eine öffentliche Wiedergabeliste handelt.</string>
<string name="error_channel_mandatory">Ein Kanal wird benötigt, wenn es sich um eine öffentliche Wiedergabeliste handelt.</string>
<string name="action_playlist_create">Wiedergabeliste erstellen</string>
<string name="action_playlist_empty_content">Diese Wiedergabeliste ist leer.</string>
<string name="edit_media">Medien bearbeiten</string>
<string name="redo">Wiederherstellen</string>
<string name="gallery">Galerie</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Radierer</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Anpassen</string>
<string name="label_brush">Pinsel</string>
<string name="confirm_exit_editing">Möchten Sie die Grafik wirklich verlassen, ohne sie zu speichern?</string>
<string name="discard">Verwerfen</string>
<string name="saving">Speichern …</string>
<string name="image_saved">Grafik erfolgreich gespeichert!</string>
<string name="save_image_failed">Grafik konnte nicht gespeichert werden</string>
<string name="opacity">Deckkraft</string>
<string name="label_crop">Zuschneiden</string>
<string name="set_photo_editor">Fotobearbeitung aktivieren</string>
<plurals name="number_of_vote">
<item quantity="one">%d Stimme</item>
<item quantity="other">%d Stimmen</item>

View File

@ -856,6 +856,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d ψήφοι</item>

View File

@ -850,6 +850,24 @@ https://yandex.ru/legal/confidential/?lang=en </string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -844,17 +844,35 @@
<string name="display_timeline">Bistaratu denbora-lerroak</string>
<string name="set_display_bot_icon">Markatu bot kontuak toot-etan</string>
<string name="add_tags">Kudeatu etiketak</string>
<string name="set_remember_position">Remember the position in Home timeline</string>
<string name="history">History</string>
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="privacy">Privacy</string>
<string name="create">Create</string>
<string name="action_playlist_add">You don\'t have any playlists. Click on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="set_remember_position">Gogoratu posizioa hasiera debora-lerroan</string>
<string name="history">Historiala</string>
<string name="playlists">Erreprodukzio-zerrendak</string>
<string name="display_name">Pantaila-izena</string>
<string name="privacy">Pribatutasuna</string>
<string name="create">Sortu</string>
<string name="action_playlist_add">Ez duzu erreprodukzio-zerrendarik. Sakatu \'+\' ikonoa erreprodukzio-zerrenda berria gehitzeko</string>
<string name="error_display_name">Pantaila-izen bat eman behar duzu!</string>
<string name="error_channel_mandatory">Kanala beharrezkoa da erreprodukzio-zerrenda publikoa bada.</string>
<string name="action_playlist_create">Sortu erreprodukzio-zerrenda</string>
<string name="action_playlist_empty_content">Ez dago ezer erreprodukzio-zerrenda honetan oraindik.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">boto %d</item>
<item quantity="other">%d boto</item>

View File

@ -856,6 +856,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -856,6 +856,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -853,6 +853,24 @@ Le bouton de connexion sactivera une fois quun domaine valide sera renseig
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Galerie</string>
<string name="label_emoji">Émoji</string>
<string name="label_sticker">Autocollant</string>
<string name="label_eraser">Gomme</string>
<string name="label_text">Texte</string>
<string name="label_filter">Filtre</string>
<string name="label_adjust">Ajuster</string>
<string name="label_brush">Pinceau</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Annuler</string>
<string name="saving">Enregistrement …</string>
<string name="image_saved">Image enregistrée avec succès !</string>
<string name="save_image_failed">Échec de l\'enregistrement de l\'image</string>
<string name="opacity">Transparence</string>
<string name="label_crop">Rogner</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d voix</item>
<item quantity="other">%d voix</item>

View File

@ -857,6 +857,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d voto</item>
<item quantity="other">%d votos</item>

View File

@ -864,6 +864,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="two">%d votes</item>

View File

@ -846,6 +846,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -696,7 +696,7 @@ A Yandexnek megvan a saját adatvédelmi szabályzata, ami itt található: http
<string name="some_words_any">Bármelyik a következő szavakból (szóközzel elválasztva)</string>
<string name="some_words_all">Minden szó (szóközzel elválasztva)</string>
<string name="some_words_none">Egyik szó sem (szóközzel elválasztva)</string>
<string name="some_tags">Add some words to filter (space-separated)</string>
<string name="some_tags">Néhány szűrő szó hozzáadása (szóközzel elválasztva)</string>
<string name="change_tag_column">Oszlop nevének megváltoztatása</string>
<string name="no_misskey_instance">Nincs Misskey szerver</string>
<string name="misskey_instance">Misskey szerver</string>
@ -835,25 +835,43 @@ A Yandexnek megvan a saját adatvédelmi szabályzata, ami itt található: http
<string name="add_timeline">Idővonal hozzáadása</string>
<string name="set_sensitive_content">Minden médiát jelölj meg érzékenynek</string>
<string name="gnu_instance">GNU szerver</string>
<string name="cached_status">Cached status</string>
<string name="cached_status">Gyorsítótárazott üzenet</string>
<string name="set_forward_tags">Címkék továbbítasa a válaszokban</string>
<string name="set_long_press_media">Nyomd meg hosszan a média tárolásához</string>
<string name="set_blur_sensitive">Érzékeny média homályosítása</string>
<string name="set_display_timeline_in_list">Idővonalak megjelenítése listában</string>
<string name="display_timeline">Idővonalak megjelenítése</string>
<string name="set_display_bot_icon">Mark bot accounts in toots</string>
<string name="add_tags">Manage tags</string>
<string name="set_display_bot_icon">Bot-fiókok megjelölése a tootokban</string>
<string name="add_tags">Címkék kezelése</string>
<string name="set_remember_position">Remember the position in Home timeline</string>
<string name="history">History</string>
<string name="playlists">Playlists</string>
<string name="display_name">Display name</string>
<string name="privacy">Privacy</string>
<string name="create">Create</string>
<string name="action_playlist_add">You don\'t have any playlists. Click on the \"+\" icon to add a new playlist</string>
<string name="error_display_name">You must provide a display name!</string>
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="history">Előzmények</string>
<string name="playlists">Lejátszási listák</string>
<string name="display_name">Megjelenítendő név</string>
<string name="privacy">Adatvédelem</string>
<string name="create">Létrehoz</string>
<string name="action_playlist_add">Nincs még lejátszási listád. Klikkelj a \'+\' jelre új lejátszási lista hozzáadásához</string>
<string name="error_display_name">Meg kell adnod egy megjelenítési nevet!</string>
<string name="error_channel_mandatory">Csatorna kiválasztása szükséges, ha a lejátszási lista nyilvános.</string>
<string name="action_playlist_create">Lejátszási lista létrehozása</string>
<string name="action_playlist_empty_content">Ez a lejátszási list még üres.</string>
<string name="edit_media">Média szerkesztése</string>
<string name="redo">Ismétlés</string>
<string name="gallery">Galéria</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Matrica</string>
<string name="label_eraser">Radír</string>
<string name="label_text">Szöveg</string>
<string name="label_filter">Szűrő</string>
<string name="label_adjust">Beállítás</string>
<string name="label_brush">Ecset</string>
<string name="confirm_exit_editing">Biztos, hogy a kép mentése nélkül kilép?</string>
<string name="discard">Elvet</string>
<string name="saving">Mentés folyamatban…</string>
<string name="image_saved">A kép sikeresen elmentve!</string>
<string name="save_image_failed">Nem sikerült elmenteni a képet</string>
<string name="opacity">Áttetszőség</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d szavazat</item>
<item quantity="other">%d szavazat</item>

View File

@ -855,6 +855,24 @@
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="one">%d vote</item>
<item quantity="other">%d votes</item>

View File

@ -854,6 +854,24 @@ https://yandex.ru/legal/confidential/?lang=en
<string name="error_channel_mandatory">The channel is required when the playlist is public.</string>
<string name="action_playlist_create">Create a playlist</string>
<string name="action_playlist_empty_content">There is nothing in this playlist yet.</string>
<string name="edit_media">Edit media</string>
<string name="redo">redo</string>
<string name="gallery">Gallery</string>
<string name="label_emoji">Emoji</string>
<string name="label_sticker">Sticker</string>
<string name="label_eraser">Eraser</string>
<string name="label_text">Text</string>
<string name="label_filter">Filter</string>
<string name="label_adjust">Adjust</string>
<string name="label_brush">Brush</string>
<string name="confirm_exit_editing">Are you sure to exit without saving the image?</string>
<string name="discard">Discard</string>
<string name="saving">Saving…</string>
<string name="image_saved">Image Saved Successfully!</string>
<string name="save_image_failed">Failed to save Image</string>
<string name="opacity">Opacity</string>
<string name="label_crop">Crop</string>
<string name="set_photo_editor">Enable photo editor</string>
<plurals name="number_of_vote">
<item quantity="other">%d votes</item>
</plurals>

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