Merge pull request #213 from LucasGGamerM/feature/camera-compose-shortcut

feat: add camera shortcut to compose screen
This commit is contained in:
LucasGGamerM
2023-06-11 18:13:39 -03:00
committed by GitHub
7 changed files with 116 additions and 15 deletions

View File

@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>

View File

@@ -1,20 +1,28 @@
package org.joinmastodon.android;
import static org.joinmastodon.android.fragments.ComposeFragment.CAMERA_PERMISSION_CODE;
import static org.joinmastodon.android.fragments.ComposeFragment.CAMERA_PIC_REQUEST_CODE;
import android.Manifest;
import android.app.Activity;
import android.app.Fragment;
import android.app.assist.AssistContent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;
import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.PictureTakenEvent;
import org.joinmastodon.android.fragments.ComposeFragment;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.fragments.ProfileFragment;
@@ -189,6 +197,27 @@ public class MainActivity extends FragmentStackActivity implements ProvidesAssis
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode==CAMERA_PIC_REQUEST_CODE && resultCode== Activity.RESULT_OK){
Bitmap image = (Bitmap) data.getExtras().get("data");
String path = MediaStore.Images.Media.insertImage(this.getContentResolver(), image, null, null);
E.post(new PictureTakenEvent(Uri.parse(path)));
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION_CODE && (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST_CODE);
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_SHORT);
}
}
public Fragment getCurrentFragment() {
for (int i = fragmentContainers.size() - 1; i >= 0; i--) {
FrameLayout fl = fragmentContainers.get(i);

View File

@@ -0,0 +1,13 @@
package org.joinmastodon.android.events;
import android.net.Uri;
import org.joinmastodon.android.model.Poll;
public class PictureTakenEvent {
public Uri uri;
public PictureTakenEvent(Uri uri){
this.uri = uri;
}
}

View File

@@ -1,7 +1,5 @@
package org.joinmastodon.android.fragments;
import static android.os.ext.SdkExtensions.getExtensionVersion;
import static org.joinmastodon.android.GlobalUserPreferences.recentLanguages;
import static org.joinmastodon.android.api.requests.statuses.CreateStatus.DRAFTS_AFTER_INSTANT;
import static org.joinmastodon.android.api.requests.statuses.CreateStatus.getDraftInstant;
@@ -9,6 +7,7 @@ import static org.joinmastodon.android.ui.utils.UiUtils.isPhotoPickerAvailable;
import static org.joinmastodon.android.utils.MastodonLanguage.allLanguages;
import static org.joinmastodon.android.utils.MastodonLanguage.defaultRecentLanguages;
import android.Manifest;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -17,6 +16,7 @@ import android.app.TimePickerDialog;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -29,7 +29,6 @@ import android.graphics.drawable.LayerDrawable;
import android.icu.text.BreakIterator;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.opengl.Visibility;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
@@ -70,7 +69,10 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.github.bottomSoftwareFoundation.bottom.Bottom;
import com.squareup.otto.Subscribe;
import com.twitter.twittertext.TwitterTextEmojiRegex;
import org.joinmastodon.android.E;
@@ -87,11 +89,14 @@ import org.joinmastodon.android.api.requests.statuses.GetAttachmentByID;
import org.joinmastodon.android.api.requests.statuses.UploadAttachment;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.PictureTakenEvent;
import org.joinmastodon.android.events.ScheduledStatusCreatedEvent;
import org.joinmastodon.android.events.ScheduledStatusDeletedEvent;
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.events.StatusUpdatedEvent;
import org.joinmastodon.android.fragments.settings.SettingsBaseFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.ContentType;
@@ -113,6 +118,7 @@ import org.joinmastodon.android.ui.text.ComposeAutocompleteSpan;
import org.joinmastodon.android.ui.text.ComposeHashtagOrMentionSpan;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.updater.GithubSelfUpdater;
import org.joinmastodon.android.utils.TransferSpeedTracker;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ComposeEditText;
@@ -161,6 +167,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private static final String GLITCH_LOCAL_ONLY_SUFFIX = "👁";
private static final Pattern GLITCH_LOCAL_ONLY_PATTERN = Pattern.compile("[\\s\\S]*" + GLITCH_LOCAL_ONLY_SUFFIX + "[\uFE00-\uFE0F]*");
private static final String TAG="ComposeFragment";
public static final int CAMERA_PERMISSION_CODE = 626938;
public static final int CAMERA_PIC_REQUEST_CODE = 6242069;
public static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
@@ -246,6 +254,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
E.register(this);
setRetainInstance(true);
navigationBarColorBefore = getActivity().getWindow().getNavigationBarColor();
getActivity().getWindow().setNavigationBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorBackgroundLightest));
@@ -286,6 +295,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
@Override
public void onDestroy(){
super.onDestroy();
E.unregister(this);
for(DraftMediaAttachment att:attachments){
if(att.isUploadingOrProcessing())
att.cancelUpload();
@@ -365,19 +375,28 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
view.findViewById(GlobalUserPreferences.replyLineAboveHeader ? R.id.reply_text_below : R.id.reply_text)
.setVisibility(View.GONE);
if (isPhotoPickerAvailable()) {
PopupMenu attachPopup = new PopupMenu(getContext(), mediaBtn);
attachPopup.inflate(R.menu.attach);
attachPopup.setOnMenuItemClickListener(i -> {
PopupMenu attachPopup = new PopupMenu(getContext(), mediaBtn);
attachPopup.inflate(R.menu.attach);
if(isPhotoPickerAvailable())
attachPopup.getMenu().findItem(R.id.media).setVisible(true);
attachPopup.setOnMenuItemClickListener(i -> {
if (i.getItemId() == R.id.camera){
if (getContext().checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST_CODE);
} else {
getActivity().requestPermissions(new String[] { Manifest.permission.CAMERA }, CAMERA_PERMISSION_CODE);
}
} else {
openFilePicker(i.getItemId() == R.id.media);
return true;
});
UiUtils.enablePopupMenuIcons(getContext(), attachPopup);
mediaBtn.setOnClickListener(v->attachPopup.show());
mediaBtn.setOnTouchListener(attachPopup.getDragToOpenListener());
} else {
mediaBtn.setOnClickListener(v -> openFilePicker(false));
}
}
return true;
});
UiUtils.enablePopupMenuIcons(getContext(), attachPopup);
mediaBtn.setOnClickListener(v->attachPopup.show());
mediaBtn.setOnTouchListener(attachPopup.getDragToOpenListener());
if (isInstancePixelfed()) pollBtn.setVisibility(View.GONE);
pollBtn.setOnClickListener(v->togglePoll());
emojiBtn.setOnClickListener(v->emojiKeyboard.toggleKeyboardPopup(mainEditText));
@@ -569,6 +588,19 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if (scheduledStatus != null) outState.putParcelable("scheduledStatus", Parcels.wrap(scheduledStatus));
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CAMERA_PERMISSION_CODE && (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST_CODE);
} else {
Toast.makeText(getContext(), R.string.permission_required, Toast.LENGTH_SHORT);
}
}
@Override
public void onResume(){
super.onResume();
@@ -1427,6 +1459,17 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
}
}
if(requestCode==CAMERA_PIC_REQUEST_CODE && resultCode==Activity.RESULT_OK){
Bitmap image = (Bitmap) data.getExtras().get("data");
String path = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), image, null, null);
addMediaAttachment(Uri.parse(path), null);
}
}
@Subscribe
public void onPictureTaken(PictureTakenEvent ev){
addMediaAttachment(ev.uri, null);
}
private boolean addMediaAttachment(Uri uri, String description){

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"
android:viewportHeight="24">
<path
android:pathData="M13.925,2.504C14.722,2.504 15.461,2.926 15.865,3.614L16.679,5.001H18.75C20.545,5.001 22,6.456 22,8.251V17.751C22,19.546 20.545,21.001 18.75,21.001H5.25C3.455,21.001 2,19.546 2,17.751V8.251C2,6.456 3.455,5.001 5.25,5.001H7.33L8.205,3.577C8.614,2.91 9.34,2.504 10.122,2.504H13.925ZM13.925,4.004H10.122C9.899,4.004 9.689,4.103 9.548,4.272L9.483,4.361L8.389,6.143C8.253,6.365 8.011,6.501 7.75,6.501H5.25C4.284,6.501 3.5,7.284 3.5,8.251V17.751C3.5,18.717 4.284,19.501 5.25,19.501H18.75C19.716,19.501 20.5,18.717 20.5,17.751V8.251C20.5,7.284 19.716,6.501 18.75,6.501H16.25C15.984,6.501 15.738,6.36 15.603,6.131L14.571,4.374C14.437,4.145 14.191,4.004 13.925,4.004ZM12,8.001C14.485,8.001 16.5,10.016 16.5,12.501C16.5,14.986 14.485,17.001 12,17.001C9.515,17.001 7.5,14.986 7.5,12.501C7.5,10.016 9.515,8.001 12,8.001ZM12,9.501C10.343,9.501 9,10.844 9,12.501C9,14.158 10.343,15.501 12,15.501C13.657,15.501 15,14.158 15,12.501C15,10.844 13.657,9.501 12,9.501Z"
android:fillColor="#212121"/>
</vector>

View File

@@ -3,9 +3,14 @@
<item
android:id="@+id/media"
android:title="@string/add_media"
android:visible="false"
android:icon="@drawable/ic_fluent_image_24_regular" />
<item
android:id="@+id/file"
android:title="@string/sk_attach_file"
android:icon="@drawable/ic_fluent_document_24_regular" />
<item
android:id="@+id/camera"
android:title="@string/mo_open_camera"
android:icon="@drawable/ic_fluent_camera_24_regular" />
</menu>

View File

@@ -32,6 +32,7 @@
<string name="mo_change_default_reply_visibility_to_unlisted">Reply as \'Unlisted\' by default</string>
<string name="mo_composer_behavior">Composer\'s Behavior</string>
<string name="mo_notification_management_settings">Manage Notifications</string>
<string name="mo_open_camera">Take picture</string>
<!-- accessibility labels-->
<string name="mo_poll_option_add">Add new poll option</string>