diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 7e7ee626..61a9130c 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index c4e42dc4..58918f50 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Houseclub/build.gradle b/Houseclub/build.gradle index 3b477dcb..1febac31 100644 --- a/Houseclub/build.gradle +++ b/Houseclub/build.gradle @@ -9,6 +9,13 @@ android { targetSdkVersion 30 versionCode 9 versionName "1.0.8" + + Properties properties = new Properties() + if (project.rootProject.file('local.properties').canRead()) { + properties.load(project.rootProject.file("local.properties").newDataInputStream()) + } + + buildConfigField "String", "INSTAGRAM_APP_ID", '"'+properties.getProperty("instagramAppId")+'"' } buildTypes { release { diff --git a/Houseclub/src/main/java/me/grishka/houseclub/MainActivity.java b/Houseclub/src/main/java/me/grishka/houseclub/MainActivity.java index f54d8c1c..3bbc6c32 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/MainActivity.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/MainActivity.java @@ -3,6 +3,7 @@ import android.Manifest; import android.app.Activity; import android.app.AlertDialog; +import android.app.Fragment; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -24,9 +25,12 @@ import me.grishka.houseclub.api.ClubhouseSession; import me.grishka.houseclub.api.methods.CheckWaitlistStatus; import me.grishka.houseclub.api.methods.GetChannel; +import me.grishka.houseclub.api.methods.GetClub; import me.grishka.houseclub.api.methods.GetEvent; import me.grishka.houseclub.api.methods.JoinChannel; import me.grishka.houseclub.api.model.Channel; +import me.grishka.houseclub.api.model.Club; +import me.grishka.houseclub.fragments.ClubFragment; import me.grishka.houseclub.fragments.HomeFragment; import me.grishka.houseclub.fragments.InChannelFragment; import me.grishka.houseclub.fragments.LoginFragment; @@ -35,14 +39,14 @@ public class MainActivity extends FragmentStackActivity{ - private Channel channelToJoin; + private String channelToJoin; private static final int PERMISSION_RESULT=270; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); - SharedPreferences prefs=getPreferences(MODE_PRIVATE); + if(!prefs.getBoolean("warningShown", false)){ new AlertDialog.Builder(this) .setTitle(R.string.warning) @@ -94,6 +98,7 @@ public void onError(ErrorResponse error){ } }else{ showFragment(new LoginFragment()); + } } @@ -157,7 +162,7 @@ public void onSuccess(final Channel result){ .setPositiveButton(R.string.join, new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialogInterface, int i){ - joinChannel(result); + joinChannel(result.channel); } }) .setNegativeButton(R.string.cancel, null) @@ -172,10 +177,10 @@ public void onError(ErrorResponse error){ .exec(); } - public void joinChannel(Channel chan){ + public void joinChannel(String chan){ if(VoiceService.getInstance()!=null){ Channel current=VoiceService.getInstance().getChannel(); - if(current.channel.equals(chan.channel)){ + if(current.channel.equals(chan)){ Bundle extras=new Bundle(); extras.putBoolean("_can_go_back", true); InChannelFragment fragment=new InChannelFragment(); @@ -186,7 +191,7 @@ public void joinChannel(Channel chan){ VoiceService.getInstance().leaveChannel(); } if(checkSelfPermission(Manifest.permission.RECORD_AUDIO)==PackageManager.PERMISSION_GRANTED){ - new JoinChannel(chan.channel) + new JoinChannel(chan) .wrapProgress(this) .setCallback(new Callback(){ @Override diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/ClubhouseAPIController.java b/Houseclub/src/main/java/me/grishka/houseclub/api/ClubhouseAPIController.java index 68a9ac36..e622c0c4 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/api/ClubhouseAPIController.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/ClubhouseAPIController.java @@ -31,9 +31,9 @@ public class ClubhouseAPIController{ private static final Uri API_URL=Uri.parse("https://www.clubhouseapi.com/api"); // private static final Uri API_URL=Uri.parse("http://192.168.0.51:8080/"); - private static final String API_BUILD_ID="304"; - private static final String API_BUILD_VERSION="0.1.28"; - private static final String API_UA="clubhouse/"+API_BUILD_ID+" (iPhone; iOS 13.5.1; Scale/3.00)"; + public static final String API_BUILD_ID="304"; + public static final String API_BUILD_VERSION="0.1.28"; + public static final String API_UA="clubhouse/"+API_BUILD_ID+" (iPhone; iOS 13.5.1; Scale/3.00)"; public static final String PUBNUB_PUB_KEY = "pub-c-6878d382-5ae6-4494-9099-f930f938868b"; public static final String PUBNUB_SUB_KEY = "sub-c-a4abea84-9ca3-11ea-8e71-f2b83ac9263d"; @@ -41,6 +41,9 @@ public class ClubhouseAPIController{ public static final String TWITTER_ID = "NyJhARWVYU1X3qJZtC2154xSI"; public static final String TWITTER_SECRET = "ylFImLBFaOE362uwr4jut8S8gXGWh93S1TUKbkfh7jDIPse02o"; + public static final String INSTAGRAM_ID = "1352866981588597"; + public static final String INSTAGRAM_CALLBACK = "https://www.joinclubhouse.com/callback/instagram"; + public static final String AGORA_KEY = "938de3e8055e42b281bb8c6f69c21f78"; public static final String SENTRY_KEY = "5374a416cd2d4009a781b49d1bd9ef44@o325556.ingest.sentry.io/5245095"; public static final String INSTABUG_KEY = "4e53155da9b00728caa5249f2e35d6b3"; @@ -150,6 +153,12 @@ public void run(){ if(DEBUG) Log.i(TAG, "Raw response: "+respStr); BaseResponse br=gson.fromJson(respStr, BaseResponse.class); + + String error; + if (!br.errorMessage.isEmpty()) error=br.errorMessage; + else error="ERROR with code " +resp.code(); + br.errorMessage = error; + req.onError(new ClubhouseErrorResponse(br)); } } diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/AudienceReply.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/AudienceReply.java index a7181252..dbd46b92 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/AudienceReply.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/AudienceReply.java @@ -4,6 +4,7 @@ import me.grishka.houseclub.api.ClubhouseAPIRequest; public class AudienceReply extends ClubhouseAPIRequest{ + public AudienceReply(String channel, boolean raise){ super("POST", "audience_reply", BaseResponse.class); requestBody=new Body(channel, raise, !raise); @@ -19,4 +20,5 @@ public Body(String channel, boolean raiseHands, boolean unraiseHands){ this.unraiseHands=unraiseHands; } } + } diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/FollowClub.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/FollowClub.java new file mode 100644 index 00000000..e1320c64 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/FollowClub.java @@ -0,0 +1,19 @@ +package me.grishka.houseclub.api.methods; + +import me.grishka.houseclub.api.BaseResponse; +import me.grishka.houseclub.api.ClubhouseAPIRequest; + +public class FollowClub extends ClubhouseAPIRequest{ + public FollowClub(int clubId){ + super("POST", "follow_club", BaseResponse.class); + requestBody=new Body(clubId); + } + + private static class Body{ + public int clubId, source=4; + + public Body(int clubId){ + this.clubId=clubId; + } + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetClub.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetClub.java new file mode 100644 index 00000000..6a886eae --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetClub.java @@ -0,0 +1,29 @@ +package me.grishka.houseclub.api.methods; + +import java.util.List; + +import me.grishka.houseclub.api.ClubhouseAPIRequest; +import me.grishka.houseclub.api.model.Club; +import me.grishka.houseclub.api.model.Topic; + +public class GetClub extends ClubhouseAPIRequest{ + + public GetClub(int id){ + super("POST", "get_club", Response.class); + requestBody=new Body(id); + } + + private static class Body{ + public int club_id; + public Body(int club_id){ this.club_id=club_id; } + } + + public static class Response{ + public Club club; + public boolean is_admin; + public boolean is_member; + public boolean is_follower; + public List topics; + } + +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetEvents.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetEvents.java new file mode 100644 index 00000000..354bc50f --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetEvents.java @@ -0,0 +1,16 @@ +package me.grishka.houseclub.api.methods; + +import java.util.List; + +import me.grishka.houseclub.api.ClubhouseAPIRequest; +import me.grishka.houseclub.api.model.Event; + +public class GetEvents extends ClubhouseAPIRequest { + public GetEvents(){ + super("GET", "get_events", Response.class); + } + + public static class Response{ + public List events; + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetProfile.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetProfile.java index af4d59e3..f999465b 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetProfile.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/GetProfile.java @@ -1,6 +1,7 @@ package me.grishka.houseclub.api.methods; import me.grishka.houseclub.api.ClubhouseAPIRequest; +import me.grishka.houseclub.api.model.Club; import me.grishka.houseclub.api.model.FullUser; public class GetProfile extends ClubhouseAPIRequest{ diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/InviteToRoom.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/InviteToRoom.java new file mode 100644 index 00000000..d001158b --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/InviteToRoom.java @@ -0,0 +1,23 @@ +package me.grishka.houseclub.api.methods; + +import me.grishka.houseclub.api.BaseResponse; +import me.grishka.houseclub.api.ClubhouseAPIRequest; + +public class InviteToRoom extends ClubhouseAPIRequest{ + + public InviteToRoom(String channel, int user_id){ + super("POST", "invite_to_existing_channel", BaseResponse.class); + requestBody=new Body(channel, user_id); + } + + private static class Body{ + public String channel; + public int user_id; + + public Body(String channel, int user_id){ + this.channel=channel; + this.user_id=user_id; + } + } + +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/SearchClubs.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/SearchClubs.java new file mode 100644 index 00000000..fa037349 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/SearchClubs.java @@ -0,0 +1,25 @@ +package me.grishka.houseclub.api.methods; + +import java.util.List; + +import me.grishka.houseclub.api.ClubhouseAPIRequest; +import me.grishka.houseclub.api.model.Club; + +public class SearchClubs extends ClubhouseAPIRequest { + public SearchClubs(String query) { + super("POST", "search_clubs", Response.class); + requestBody = new Body(query); + } + + private static class Body { + public String query; + + public Body(String query) { + this.query = query; + } + } + + public static class Response{ + public List clubs; + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/SearchPeople.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/SearchPeople.java new file mode 100644 index 00000000..b516eddc --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/SearchPeople.java @@ -0,0 +1,26 @@ +package me.grishka.houseclub.api.methods; + +import java.util.List; + +import me.grishka.houseclub.api.ClubhouseAPIRequest; +import me.grishka.houseclub.api.model.FullUser; + +public class SearchPeople extends ClubhouseAPIRequest { + public SearchPeople(String query) { + super("POST", "search_users", Resp.class); + requestBody = new Body(query); + } + + private static class Body { + public String query; + + public Body(String query) { + this.query = query; + } + } + + public static class Resp { + public List users; + public int count; + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/UnfollowClub.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/UnfollowClub.java new file mode 100644 index 00000000..d87b5066 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/UnfollowClub.java @@ -0,0 +1,19 @@ +package me.grishka.houseclub.api.methods; + +import me.grishka.houseclub.api.BaseResponse; +import me.grishka.houseclub.api.ClubhouseAPIRequest; + +public class UnfollowClub extends ClubhouseAPIRequest{ + public UnfollowClub(int clubId){ + super("POST", "unfollow_club", BaseResponse.class); + requestBody=new Body(clubId); + } + + private static class Body{ + public int clubId, source=4; + + public Body(int clubId){ + this.clubId=clubId; + } + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/methods/UpdateInstagram.java b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/UpdateInstagram.java new file mode 100644 index 00000000..07d805d0 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/methods/UpdateInstagram.java @@ -0,0 +1,19 @@ +package me.grishka.houseclub.api.methods; + +import me.grishka.houseclub.api.BaseResponse; +import me.grishka.houseclub.api.ClubhouseAPIRequest; + +public class UpdateInstagram extends ClubhouseAPIRequest{ + public static String REDIRECT_INSTAGRAM_URL = "https://www.joinclubhouse.com/callback/instagram"; + public UpdateInstagram(String code) { + super("POST", "update_instagram_username", BaseResponse.class); + requestBody = new Body(code); + } + + private static class Body{ + public String code; + Body(String code){ + this.code = code; + } + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/model/Club.java b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Club.java new file mode 100644 index 00000000..f0f4bfbe --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Club.java @@ -0,0 +1,80 @@ +package me.grishka.houseclub.api.model; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +public class Club implements Parcelable{ + + public int club_id; + public String name; + public String description; + public String photo_url; + public int num_members; + public int num_followers; + public boolean is_member; + public boolean is_follower; + + + + + @Override + public int describeContents(){ + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags){ + dest.writeInt(this.club_id); + dest.writeString(this.name); + dest.writeString(this.description); + dest.writeString(this.photo_url); + dest.writeInt(this.num_members); + dest.writeInt(this.num_followers); + dest.writeByte(this.is_member ? (byte) 1 : (byte) 0); + dest.writeByte(this.is_follower ? (byte) 1 : (byte) 0); + + + } + + public void readFromParcel(Parcel source){ + this.club_id=source.readInt(); + this.name=source.readString(); + this.description=source.readString(); + this.photo_url=source.readString(); + this.num_members=source.readInt(); + this.num_followers=source.readInt(); + this.is_member=source.readByte()!=0; + this.is_follower=source.readByte()!=0; + + } + + public Club(){ } + + protected Club(Parcel in){ + this.club_id=in.readInt(); + this.name=in.readString(); + this.description=in.readString(); + this.photo_url=in.readString(); + this.num_members=in.readInt(); + this.num_followers=in.readInt(); + this.is_member=in.readByte()!=0; + this.is_follower=in.readByte()!=0; + + + } + + public static final Creator CREATOR=new Creator(){ + @Override + public Club createFromParcel(Parcel source){ + return new Club(source); + } + + @Override + public Club[] newArray(int size){ + return new Club[size]; + } + + }; +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/model/Event.java b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Event.java index ea1ae9b8..51cbb2de 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/api/model/Event.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Event.java @@ -11,5 +11,4 @@ public class Event{ public int eventId; public boolean isMemberOnly; public List hosts; - public boolean clubIsMember, clubIsFollower; } diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/model/FullUser.java b/Houseclub/src/main/java/me/grishka/houseclub/api/model/FullUser.java index 2eef2405..1c7cdba3 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/api/model/FullUser.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/model/FullUser.java @@ -1,13 +1,18 @@ package me.grishka.houseclub.api.model; import java.util.Date; +import java.util.List; public class FullUser extends User{ public String dsplayname, bio, twitter, instagram; - public int numFollowers, numFollowing; + public int numFollowers, numFollowing ; public boolean followsMe, isBlockedByNetwork; + public int mutual_follows_count; public Date timeCreated; public User invitedByUserProfile; + public List mutualFollows; + public List clubs; + // null = not following // 2 = following // other values = ? @@ -16,4 +21,5 @@ public class FullUser extends User{ public boolean isFollowed(){ return notificationType==2; } + } diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/model/Notification.java b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Notification.java index f576bb35..f7760bfc 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/api/model/Notification.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Notification.java @@ -10,6 +10,8 @@ public class Notification { public int type; public Date timeCreated; public String message; + public String channel; +// public Channel channel; public static final int NOTIFICATION_TYPE_USER=1; public static final int NOTIFICATION_TYPE_EVENT=16; diff --git a/Houseclub/src/main/java/me/grishka/houseclub/api/model/Topic.java b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Topic.java new file mode 100644 index 00000000..c819f8b2 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/api/model/Topic.java @@ -0,0 +1,63 @@ +package me.grishka.houseclub.api.model; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Topic implements Parcelable{ + /* + +"topics": [ + { +"title": "📈 Marketing", +"id": 112, +"abbreviated_title": "Marketing" +}, + + +] + * */ + + public String title; + public int id; + public String abbreviated_title; + + + + @Override + public int describeContents(){ + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags){ + dest.writeString(this.title); + dest.writeInt(this.id); + dest.writeString(this.abbreviated_title); + } + + public void readFromParcel(Parcel source){ + this.title=source.readString(); + this.id=source.readInt(); + this.abbreviated_title=source.readString(); + } + + public Topic(){} + + protected Topic(Parcel in){ + this.title=in.readString(); + this.id=in.readInt(); + this.abbreviated_title=in.readString(); + } + + public static final Creator CREATOR=new Creator(){ + @Override + public Topic createFromParcel(Parcel source){ + return new Topic(source); + } + + @Override + public Topic[] newArray(int size){ + return new Topic[size]; + } + }; +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/ClubFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/ClubFragment.java new file mode 100644 index 00000000..33df89c6 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/ClubFragment.java @@ -0,0 +1,190 @@ +package me.grishka.houseclub.fragments; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.res.Configuration; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.stream.Collectors; + +import me.grishka.appkit.Nav; +import me.grishka.appkit.api.Callback; +import me.grishka.appkit.api.ErrorResponse; +import me.grishka.appkit.api.SimpleCallback; +import me.grishka.appkit.fragments.LoaderFragment; +import me.grishka.appkit.imageloader.ViewImageLoader; +import me.grishka.houseclub.R; +import me.grishka.houseclub.VoiceService; +import me.grishka.houseclub.api.BaseResponse; +import me.grishka.houseclub.api.ClubhouseSession; +import me.grishka.houseclub.api.methods.FollowClub; +import me.grishka.houseclub.api.methods.GetClub; +import me.grishka.houseclub.api.methods.UnfollowClub; +import me.grishka.houseclub.api.model.Club; + +public class ClubFragment extends LoaderFragment{ + + private static final int PICK_PHOTO_RESULT=468; + + private Club club; + + private boolean is_follower; + private TextView name, description, followers, members, topics , user_clubs; + private ImageView clubPhoto ; + private Button followBtn; + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + loadData(); + } + + @Override + public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ + View v=inflater.inflate(R.layout.club, container, false); + + name=v.findViewById(R.id.name); + description=v.findViewById(R.id.description); + followers=v.findViewById(R.id.followers); + members=v.findViewById(R.id.members); + topics=v.findViewById(R.id.topics); + clubPhoto=v.findViewById(R.id.clubPhoto); + + followBtn=v.findViewById(R.id.follow_btn); + + followBtn.setOnClickListener(this::onFollowClick); + + return v; + } + + @Override + protected void doLoadData(){ + + currentRequest=new GetClub(getArguments().getInt("id")) + .setCallback(new SimpleCallback(this){ + @Override + public void onSuccess(GetClub.Response result){ + currentRequest=null; + + club = result.club; + + is_follower = result.is_follower; + + name.setText(club.name); + description.setText(result.club.description); + followers.setText(( club.num_followers>0 ? String.valueOf(club.num_followers) : "0") + " followers"); + members.setText(( club.num_members>0 ? String.valueOf(club.num_members) : "0") + " members"); + + followBtn.setText(is_follower ? R.string.following : R.string.follow); + + topics.setText(result.topics.stream().map(topic->topic.title ).collect(Collectors.joining(" . ")) ); + + if(club.photo_url!=null){ + ColorDrawable d2=new ColorDrawable(getResources().getColor(R.color.grey)); + if(club.photo_url!=null) + ViewImageLoader.load(clubPhoto, d2, club.photo_url); + else + clubPhoto.setImageDrawable(d2); + }else{ + clubPhoto.setVisibility(View.GONE); + } + + + dataLoaded(); + + } + }) + .exec(); + + + + } + + @Override + public void onRefresh(){ + loadData(); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState){ + super.onViewCreated(view, savedInstanceState); + getToolbar().setElevation(0); + } + + @Override + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + getToolbar().setElevation(0); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ + menu.add(R.string.log_out); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item){ + if(VoiceService.getInstance()!=null){ + VoiceService.getInstance().leaveChannel(); + } + ClubhouseSession.userID=ClubhouseSession.userToken=null; + ClubhouseSession.write(); + Nav.goClearingStack(getActivity(), LoginFragment.class, null); + return true; + } + + private void onFollowClick(View v){ + if(is_follower){ + new AlertDialog.Builder(getActivity()) + .setMessage(getString(R.string.confirm_unfollow, club.name)) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface dialogInterface, int i){ + new UnfollowClub(club.club_id) + .wrapProgress(getActivity()) + .setCallback(new Callback(){ + @Override + public void onSuccess(BaseResponse result){ + followBtn.setText(R.string.follow); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getActivity()); + } + }) + .exec(); + } + }) + .setNegativeButton(R.string.no, null) + .show(); + }else{ + new FollowClub(club.club_id) + .wrapProgress(getActivity()) + .setCallback(new Callback(){ + @Override + public void onSuccess(BaseResponse result){ + followBtn.setText(R.string.following); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getActivity()); + } + }) + .exec(); + } + } + +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/ClubListFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/ClubListFragment.java new file mode 100644 index 00000000..ca7b48d0 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/ClubListFragment.java @@ -0,0 +1,148 @@ +package me.grishka.houseclub.fragments; + +import android.app.Activity; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import me.grishka.appkit.Nav; +import me.grishka.appkit.fragments.BaseRecyclerFragment; +import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter; +import me.grishka.appkit.imageloader.ImageLoaderViewHolder; +import me.grishka.appkit.utils.BindableViewHolder; +import me.grishka.appkit.views.UsableRecyclerView; +import me.grishka.houseclub.R; +import me.grishka.houseclub.api.ClubhouseSession; +import me.grishka.houseclub.api.model.Club; + +public abstract class ClubListFragment extends BaseRecyclerFragment{ + + private int selfID = Integer.parseInt(ClubhouseSession.userID); + private ClubListAdapter adapter; + + public ClubListFragment(){ + super(50); + } + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + loadData(); + } + + @Override + protected RecyclerView.Adapter getAdapter(){ + if(adapter==null){ + adapter=new ClubListAdapter(); + } + return adapter; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState){ + super.onViewCreated(view, savedInstanceState); + getToolbar().setElevation(0); + } + + @Override + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + getToolbar().setElevation(0); + } + + private class ClubListAdapter extends RecyclerView.Adapter implements ImageLoaderRecyclerAdapter{ + + @NonNull + @Override + public ClubViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){ + return new ClubViewHolder(); + } + + @Override + public void onBindViewHolder(@NonNull ClubViewHolder holder, int position){ + holder.bind(data.get(position)); + } + + @Override + public int getItemCount(){ + return data.size(); + } + + @Override + public int getImageCountForItem(int position) { return data.get(position).photo_url!=null ? 1 : 0;} + + @Override + public String getImageURL(int position, int image) {return data.get(position).photo_url;} + + } + + private class ClubViewHolder extends BindableViewHolder implements ImageLoaderViewHolder, UsableRecyclerView.Clickable{ + + public TextView name, numFollowers, numMembers; + public Button followBtn; + public ImageView photo; + private Drawable placeholder=new ColorDrawable(getResources().getColor(R.color.grey)); + + public ClubViewHolder(){ + super(getActivity(), R.layout.club_list_row); + + name=findViewById(R.id.name); + numFollowers=findViewById(R.id.followersCount); + numMembers=findViewById(R.id.membersCount); + followBtn=findViewById(R.id.follow_btn); + photo=findViewById(R.id.photo); + } + + @Override + public void onBind(Club item){ + name.setText(item.name); + numMembers.setText(item.num_members + " members"); + numFollowers.setText(item.num_followers + " followers"); + + // TODO get_followers/get_following don't return current follow status? +// if(item.userId==selfID){ + followBtn.setVisibility(View.GONE); +// }else{ +// followBtn.setVisibility(View.VISIBLE); +// followBtn.setText(item.isFollowed() ? R.string.following : R.string.follow); +// } + + + if(item.photo_url!=null) + imgLoader.bindViewHolder(adapter, this, getAdapterPosition()); + else + photo.setImageDrawable(placeholder); + + + } + + @Override + public void setImage(int index, Bitmap bitmap){ + photo.setImageBitmap(bitmap); + } + + @Override + public void clearImage(int index){ + photo.setImageDrawable(placeholder); + } + + @Override + public void onClick(){ + Bundle args=new Bundle(); + args.putInt("id", item.club_id); + Nav.go(getActivity(), ClubFragment.class, args); + } + + + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/EventsFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/EventsFragment.java new file mode 100644 index 00000000..d0e4e53b --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/EventsFragment.java @@ -0,0 +1,270 @@ +package me.grishka.houseclub.fragments; + +import android.Manifest; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.Outline; +import android.graphics.Rect; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.stream.Collectors; + +import me.grishka.appkit.api.Callback; +import me.grishka.appkit.api.ErrorResponse; +import me.grishka.appkit.api.SimpleCallback; +import me.grishka.appkit.fragments.BaseRecyclerFragment; +import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter; +import me.grishka.appkit.imageloader.ImageLoaderViewHolder; +import me.grishka.appkit.utils.BindableViewHolder; +import me.grishka.appkit.utils.V; +import me.grishka.houseclub.MainActivity; +import me.grishka.houseclub.R; +import me.grishka.houseclub.VoiceService; +import me.grishka.houseclub.api.methods.GetChannel; +import me.grishka.houseclub.api.methods.GetEvent; +import me.grishka.houseclub.api.methods.GetEvents; +import me.grishka.houseclub.api.methods.JoinChannel; +import me.grishka.houseclub.api.model.Channel; +import me.grishka.houseclub.api.model.Event; + +public class EventsFragment extends BaseRecyclerFragment{ + + private EventsAdapter adapter; + private ViewOutlineProvider roundedCornersOutline =new ViewOutlineProvider(){ + @Override + public void getOutline(View view, Outline outline){ + outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), V.dp(8)); + } + }; + + public EventsFragment(){ + super(20); + } + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + setTitle(R.string.event_title); + loadData(); + setHasOptionsMenu(true); + } + + @Override + protected void doLoadData(int offset, int count){ + currentRequest=new GetEvents() + .setCallback(new SimpleCallback(this){ + @Override + public void onSuccess(GetEvents.Response result){ + currentRequest=null; + onDataLoaded(result.events, false); + } + }).exec(); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState){ + super.onViewCreated(view, savedInstanceState); + list.addItemDecoration(new RecyclerView.ItemDecoration(){ + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){ + outRect.bottom=outRect.top=V.dp(8); + outRect.left=outRect.right=V.dp(16); + } + }); + getToolbar().setElevation(0); + } + + @Override + public void onConfigurationChanged(Configuration newConfig){ + super.onConfigurationChanged(newConfig); + getToolbar().setElevation(0); + } + + @Override + protected RecyclerView.Adapter getAdapter(){ + if(adapter==null){ + adapter=new EventsAdapter(); + adapter.setHasStableIds(true); + } + return adapter; + } + + @Override + public boolean wantsLightNavigationBar(){ + return true; + } + + @Override + public boolean wantsLightStatusBar(){ + return true; + } + + private class EventsAdapter extends RecyclerView.Adapter implements ImageLoaderRecyclerAdapter{ + + @NonNull + @Override + public EventViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){ + return new EventViewHolder(); + } + + @Override + public void onBindViewHolder(@NonNull EventViewHolder holder, int position){ + holder.bind(data.get(position)); + } + + @Override + public int getItemCount(){ + return data.size(); + } + + @Override + public long getItemId(int position){ + return data.get(position).eventId; + } + + @Override + public int getImageCountForItem(int position){ + Event eve= data.get(position); + int count=0; + for(int i=0;i implements View.OnClickListener, ImageLoaderViewHolder{ + + private TextView start_at , topic, hosts,description; + private ImageView pic1, pic2; + private Drawable placeholder=new ColorDrawable(getResources().getColor(R.color.grey)); + + + public EventViewHolder() { + super(getActivity(), R.layout.event_row); + start_at=findViewById(R.id.event_start_time); + topic=findViewById(R.id.topic); + description=findViewById(R.id.description); + hosts=findViewById(R.id.hosts); + pic1=findViewById(R.id.pic1); + pic2=findViewById(R.id.pic2); + + itemView.setOutlineProvider(roundedCornersOutline); + itemView.setClipToOutline(true); + itemView.setElevation(V.dp(2)); + itemView.setOnClickListener(this); + + } + + + + @Override + public void onBind(Event item){ + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy hh:mm"); + String strDate = dateFormat.format(item.timeStart); + start_at.setText(strDate); + + topic.setText(item.name); + + description.setText(item.description); + + hosts.setText( + + item.hosts.stream() + .map(hosts-> hosts.name) + .collect(Collectors.joining("\n")) + ); + + imgLoader.bindViewHolder(adapter, this, getAdapterPosition()); + } + + @Override + public void onClick(View view) { + } + + private void joinChannelById(String id){ + new GetChannel(id) + .wrapProgress(getActivity()) + .setCallback(new Callback(){ + @Override + public void onSuccess(final Channel result){ + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.join_this_room) + .setMessage(result.topic) + .setPositiveButton(R.string.join, new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface dialogInterface, int i){ +// joinChannel(result); + } + }) + .setNegativeButton(R.string.cancel, null) + .show(); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getActivity()); + } + }) + .exec(); + } + + + + private ImageView imgForIndex(int index){ + if(index==0) + return pic1; + return pic2; + } + + @Override + public void setImage(int index, Bitmap bitmap) { + if(index==0 && item.hosts.get(0).photoUrl==null) + index=1; + imgForIndex(index).setImageBitmap(bitmap); + } + + @Override + public void clearImage(int index){ + imgForIndex(index).setImageDrawable(placeholder); + } + + + } +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/HomeFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/HomeFragment.java index c901025b..0efb10e6 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/fragments/HomeFragment.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/HomeFragment.java @@ -113,20 +113,49 @@ public boolean wantsLightStatusBar(){ @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ - menu.add(0,0,0,"").setIcon(R.drawable.ic_notifications).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - menu.add(0,1,0,"").setIcon(R.drawable.ic_baseline_person_24).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); +// menu.add(0,0,0,"").setIcon(R.drawable.ic_notifications).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); +// menu.add(0,1,0,"").setIcon(R.drawable.ic_baseline_person_24).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + + inflater.inflate(R.menu.menu_home, menu); + + + } @Override public boolean onOptionsItemSelected(MenuItem item){ - Bundle args=new Bundle(); - args.putInt("id", Integer.parseInt(ClubhouseSession.userID)); - if(item.getItemId()==0) { - Nav.go(getActivity(), NotificationListFragment.class, args); - } else if(item.getItemId()==1){ + if (item.getItemId() == R.id.homeMenuProfile) { + Bundle args=new Bundle(); + args.putInt("id", Integer.parseInt(ClubhouseSession.userID)); Nav.go(getActivity(), ProfileFragment.class, args); + return true; } - return true; + else if (item.getItemId() == R.id.homeMenuSearchPeople) { + Bundle args = new Bundle(); + Nav.go(getActivity(), SearchListFragment.class, args); + return true; + } + else if (item.getItemId() == R.id.homeMenuNotifications) { + Bundle args = new Bundle(); + args.putInt("id", Integer.parseInt(ClubhouseSession.userID)); + Nav.go(getActivity(), NotificationListFragment.class, args); + return true; + } + else if (item.getItemId() == R.id.homeMenuEvents) { + Bundle args = new Bundle(); + args.putInt("id", Integer.parseInt(ClubhouseSession.userID)); + Nav.go(getActivity(), EventsFragment.class, args); + return true; + } + + else if (item.getItemId() == R.id.homeMenuSearchClubs) { + Bundle args = new Bundle(); + args.putInt("id", Integer.parseInt(ClubhouseSession.userID)); + Nav.go(getActivity(), SearchClubsListFragment.class, args); + return true; + } + return super.onOptionsItemSelected(item); + } private class ChannelAdapter extends RecyclerView.Adapter implements ImageLoaderRecyclerAdapter{ @@ -204,14 +233,14 @@ public void onBind(Channel item){ topic.setText(item.topic); numMembers.setText(""+item.numAll); numSpeakers.setText(""+item.numSpeakers); - speakers.setText(item.users.stream().map(user->user.isSpeaker ? (user.name+" 💬") : user.name).collect(Collectors.joining("\n"))); + speakers.setText(item.users.stream().map(user->user.isSpeaker ? (user.name+" 💬") : user.name).collect(Collectors.joining("\n")) ); imgLoader.bindViewHolder(adapter, this, getAdapterPosition()); } @Override public void onClick(View view){ - ((MainActivity)getActivity()).joinChannel(item); + ((MainActivity)getActivity()).joinChannel(item.channel); } private ImageView imgForIndex(int index){ diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/InChannelFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/InChannelFragment.java index 11f96414..ee26b9d8 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/fragments/InChannelFragment.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/InChannelFragment.java @@ -8,12 +8,14 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.se.omapi.Session; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import java.util.ArrayList; import java.util.List; @@ -48,7 +50,7 @@ public class InChannelFragment extends BaseRecyclerFragment impleme private MergeRecyclerAdapter adapter; private UserListAdapter speakersAdapter, followedAdapter, othersAdapter; private ImageButton muteBtn; - private Button raiseBtn; + private Button raiseBtn , invite_to_room; private Channel channel; private ArrayList speakers=new ArrayList<>(), followedBySpeakers=new ArrayList<>(), otherUsers=new ArrayList<>(); private ArrayList mutedUsers=new ArrayList<>(), speakingUsers=new ArrayList<>(); @@ -68,9 +70,11 @@ public void onViewCreated(View view, Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); view.findViewById(R.id.leave).setOnClickListener(this::onLeaveClick); + invite_to_room=view.findViewById(R.id.invite_to_room); raiseBtn=view.findViewById(R.id.raise); muteBtn=view.findViewById(R.id.mute); + invite_to_room.setOnClickListener(this::onInviteClick); raiseBtn.setOnClickListener(this::onRaiseClick); muteBtn.setOnClickListener(this::onMuteClick); @@ -153,12 +157,23 @@ private void onLeaveClick(View v){ Nav.finish(this); } - private void onRaiseClick(View v){ - VoiceService svc=VoiceService.getInstance(); - if(svc.isHandRaised()) + private void onRaiseClick(View v) { + VoiceService svc = VoiceService.getInstance(); + if(svc.isHandRaised()){ + Toast.makeText(getActivity(), "Hand UnRaised", Toast.LENGTH_SHORT).show(); svc.unraiseHand(); - else + }else{ + Toast.makeText(getActivity(), "Hand Raised", Toast.LENGTH_SHORT).show(); svc.raiseHand(); + } + } + + private void onInviteClick(View v) { + Bundle args=new Bundle(); + args.putInt("id", Integer.parseInt(ClubhouseSession.userID)); + args.putString("channel", channel.channel); + args.putString("type", "invite_to_room"); + Nav.go(getActivity(), InviteToRoomFragment.class, args); } private void onMuteClick(View v){ diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/InviteToRoomFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/InviteToRoomFragment.java new file mode 100644 index 00000000..ed5ce776 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/InviteToRoomFragment.java @@ -0,0 +1,29 @@ +package me.grishka.houseclub.fragments; + +import android.app.Activity; + +import me.grishka.appkit.api.SimpleCallback; +import me.grishka.houseclub.R; +import me.grishka.houseclub.api.methods.GetFollowers; + +public class InviteToRoomFragment extends UserListFragment{ + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + setTitle(R.string.invite_to_room); + } + + @Override + protected void doLoadData(int offset, int count){ + currentRequest=new GetFollowers(getArguments().getInt("id"), 50, offset/50+1) + .setCallback(new SimpleCallback(this){ + @Override + public void onSuccess(GetFollowers.Response result){ + currentRequest=null; + onDataLoaded(result.users, data.size()+preloadedData.size()+result.users.size() 0 ){ + + followed_by.setText(" Followed by "); + + String usernames = ""; + + for(int i = 0 ; i< user.mutualFollows.size(); i++){ + + if(i>0){ + usernames += ", "+user.mutualFollows.get(i).username; + }else{ + usernames += user.mutualFollows.get(i).username; + } + + if(i == 0){ + if(user.mutualFollows.get(i).photoUrl != null){ + ColorDrawable d2=new ColorDrawable(getResources().getColor(R.color.grey)); + if(user.mutualFollows.get(i).photoUrl!=null) { + pic1.setVisibility(View.VISIBLE); + ViewImageLoader.load(pic1, d2, user.mutualFollows.get(i).photoUrl); + }else{ + pic1.setImageDrawable(d2); + } + }else{ + pic1.setVisibility(View.GONE); + } + } + + if(i == 1){ + if(user.mutualFollows.get(i).photoUrl !=null){ + ColorDrawable d2=new ColorDrawable(getResources().getColor(R.color.grey)); + if(user.mutualFollows.get(i).photoUrl!=null) { + pic2.setVisibility(View.VISIBLE); + ViewImageLoader.load(pic2, d2, user.mutualFollows.get(i).photoUrl); + }else{ + pic2.setImageDrawable(d2); + } + }else{ + pic2.setVisibility(View.GONE); + } + } + + if(i == 2){ + + if( user.mutualFollows.get(i).photoUrl !=null){ + ColorDrawable d2=new ColorDrawable(getResources().getColor(R.color.grey)); + if(user.mutualFollows.get(i).photoUrl!=null) { + pic3.setVisibility(View.VISIBLE); + ViewImageLoader.load(pic3, d2, user.mutualFollows.get(i).photoUrl); + }else{ + pic3.setImageDrawable(d2); + } + }else{ + pic3.setVisibility(View.GONE); + } + + } + + } + + if((user.mutual_follows_count - 3) > 0){ + usernames += " and " + (user.mutual_follows_count - 3) + " others"; + } + + mutuals.setText(usernames); + + } + inviteInfo.setText(joined); + if(user.clubs.size() > 0){ + + member_of_text.setText("Member of"); + user_clubs.setText(result.userProfile.clubs.stream().map(club->club.name ). + collect(Collectors.joining(" . ")) ); + + + + } + + + dataLoaded(); + } }) .exec(); + loadInvites(); } + @Override public void onRefresh(){ loadData(); @@ -186,7 +321,6 @@ public void onConfigurationChanged(Configuration newConfig){ getToolbar().setElevation(0); } - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){ menu.add(R.string.log_out); @@ -288,9 +422,98 @@ public void onError(ErrorResponse error){ } private void onInstagramClick(View v){ + if (self){ + HashMap headers = new HashMap<>(); + headers.put("CH-AppBuild", ClubhouseAPIController.API_BUILD_ID); + headers.put("CH-AppVersion", ClubhouseAPIController.API_BUILD_VERSION); + headers.put("User-Agent", ClubhouseAPIController.API_UA); + + headers.put("CH-DeviceId", ClubhouseSession.deviceID); + headers.put("Authorization", "Token "+ClubhouseSession.userToken); + headers.put("CH-UserID", ClubhouseSession.userID); + + if (user.instagram == null) { + webView.setVisibility(View.VISIBLE); + webView.setWebViewClient(new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + Boolean redirect = checkRedirect(request.getUrl().toString()); + view.loadUrl(request.getUrl().toString()); + return redirect; + } + + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Boolean redirect = checkRedirect(url); + view.loadUrl(url); + return redirect; + } + }); + webView.loadUrl( + "https://www.instagram.com/oauth/authorize?client_id=" + + "1352866981588597" + + "&redirect_uri=" + UpdateInstagram.REDIRECT_INSTAGRAM_URL + + "&scope=user_profile" + + "&response_type=code", + headers + ); + } else { + new AlertDialog.Builder(getActivity()) + .setMessage(getString(R.string.confirm_unlink_instagram_title)) + .setMessage(getString(R.string.confirm_unlink_instagram)) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener(){ + @Override + public void onClick(DialogInterface dialogInterface, int i){ + new UpdateInstagram(null) + .wrapProgress(getActivity()) + .setCallback(new Callback(){ + @Override + public void onSuccess(BaseResponse result){ + instagram.setText(R.string.add_instagram); + webView.setVisibility(View.GONE); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getActivity()); + } + }) + .exec(); + } + }) + .setNegativeButton(R.string.no, null) + .show(); + } + } else startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://instagram.com/"+user.instagram))); } + private Boolean checkRedirect(String url){ + if (url.startsWith(UpdateInstagram.REDIRECT_INSTAGRAM_URL)) { + + // last2 chars is #_ by docs https://developers.facebook.com/docs/instagram-basic-display-api/getting-started + String code = url.substring((UpdateInstagram.REDIRECT_INSTAGRAM_URL+ "?code=").length(), url.length()-2); + + new UpdateInstagram(code) + .wrapProgress(getActivity()) + .setCallback(new Callback(){ + @Override + public void onSuccess(BaseResponse result){ + instagram.setText(R.string.instagram_linked); + webView.setVisibility(View.GONE); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(getActivity()); + } + }) + .exec(); + return false; + } else { + return true; + } + } + private void onTwitterClick(View v){ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/"+user.twitter))); } diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/SearchClubsListFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/SearchClubsListFragment.java new file mode 100644 index 00000000..e12e80d5 --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/SearchClubsListFragment.java @@ -0,0 +1,104 @@ +package me.grishka.houseclub.fragments; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.SearchView; + +import me.grishka.appkit.api.SimpleCallback; +import me.grishka.houseclub.R; +import me.grishka.houseclub.api.methods.SearchClubs; + +public class SearchClubsListFragment extends ClubListFragment { + + private SearchView searchView; + private SearchView.OnQueryTextListener onQueryTextListener; + + protected static int min_query_lenght = 2; + protected String searchQuery; + private static final long DELAY = 200; + private long timestamp = System.currentTimeMillis(); + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + setTitle(R.string.search_clubs_hint); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + View search_panel = view.inflate(getContext(), R.layout.search_panel, null); + + searchView = search_panel.findViewById(R.id.searchView); + searchView.setQueryHint(getString(R.string.search_clubs_hint)); + onQueryTextListener = new OnSearchQueryTextListener(); + + getToolbar().addView(search_panel); + } + + protected void onQueryChanged(String query) { + long currentTimeStamp = System.currentTimeMillis(); + if (currentTimeStamp - timestamp < DELAY) { + timestamp = currentTimeStamp; + return; + } + + if (query == null && min_query_lenght > 0 || query.length() <= min_query_lenght) { + timestamp = currentTimeStamp; + return; + } + timestamp = currentTimeStamp; + searchQuery = query; + loadData(); + } + + private class OnSearchQueryTextListener implements SearchView.OnQueryTextListener { + @Override + public boolean onQueryTextSubmit(String query) { + onQueryChanged(query); + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + onQueryChanged(newText); + return false; + } + } + + @Override + public void onResume() { + super.onResume(); + searchView.setOnQueryTextListener(onQueryTextListener); + } + + @Override + public void onPause() { + super.onPause(); + searchView.setOnQueryTextListener(null); + } + + @Override + protected void doLoadData(int offset, int count) { + if (currentRequest != null) { + currentRequest.cancel(); + } + + currentRequest = new SearchClubs(searchQuery) + .setCallback(new SimpleCallback(this) { + @Override + public void onSuccess(SearchClubs.Response result) { + currentRequest=null; + data.clear(); + onDataLoaded(result.clubs , false); + } + + }).exec(); + } + + + + +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/SearchListFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/SearchListFragment.java new file mode 100644 index 00000000..22bd561e --- /dev/null +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/SearchListFragment.java @@ -0,0 +1,103 @@ +package me.grishka.houseclub.fragments; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.SearchView; + +import me.grishka.appkit.api.SimpleCallback; +import me.grishka.houseclub.R; +import me.grishka.houseclub.api.methods.SearchPeople; + +public class SearchListFragment extends UserListFragment { + + private SearchView searchView; + private SearchView.OnQueryTextListener onQueryTextListener; + + protected static int min_query_lenght = 2; + protected String searchQuery; + private static final long DELAY = 200; + private long timestamp = System.currentTimeMillis(); + + @Override + public void onAttach(Activity activity){ + super.onAttach(activity); + setTitle(R.string.search_people_hint); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + View search_panel = view.inflate(getContext(), R.layout.search_panel, null); + + searchView = search_panel.findViewById(R.id.searchView); + searchView.setQueryHint(getString(R.string.search_people_hint)); + onQueryTextListener = new OnSearchQueryTextListener(); + + getToolbar().addView(search_panel); + } + + protected void onQueryChanged(String query) { + long currentTimeStamp = System.currentTimeMillis(); + if (currentTimeStamp - timestamp < DELAY) { + timestamp = currentTimeStamp; + return; + } + + if (query == null && min_query_lenght > 0 || query.length() <= min_query_lenght) { + timestamp = currentTimeStamp; + return; + } + timestamp = currentTimeStamp; + searchQuery = query; + loadData(); + } + + private class OnSearchQueryTextListener implements SearchView.OnQueryTextListener { + @Override + public boolean onQueryTextSubmit(String query) { + onQueryChanged(query); + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + onQueryChanged(newText); + return false; + } + } + + @Override + public void onResume() { + super.onResume(); + searchView.setOnQueryTextListener(onQueryTextListener); + } + + @Override + public void onPause() { + super.onPause(); + searchView.setOnQueryTextListener(null); + } + + @Override + protected void doLoadData(int offset, int count) { + if (currentRequest != null) { + currentRequest.cancel(); + } + + currentRequest = new SearchPeople(searchQuery) + .setCallback(new SimpleCallback(this) { + @Override + public void onSuccess(SearchPeople.Resp result) { + currentRequest=null; + data.clear(); + onDataLoaded(result.users, false); + } + }).exec(); + } + + + + +} diff --git a/Houseclub/src/main/java/me/grishka/houseclub/fragments/UserListFragment.java b/Houseclub/src/main/java/me/grishka/houseclub/fragments/UserListFragment.java index f767bcef..8097859d 100644 --- a/Houseclub/src/main/java/me/grishka/houseclub/fragments/UserListFragment.java +++ b/Houseclub/src/main/java/me/grishka/houseclub/fragments/UserListFragment.java @@ -1,10 +1,12 @@ package me.grishka.houseclub.fragments; import android.app.Activity; +import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -12,17 +14,29 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import me.grishka.appkit.Nav; +import me.grishka.appkit.api.Callback; +import me.grishka.appkit.api.ErrorResponse; +import me.grishka.appkit.api.SimpleCallback; import me.grishka.appkit.fragments.BaseRecyclerFragment; import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter; import me.grishka.appkit.imageloader.ImageLoaderViewHolder; import me.grishka.appkit.utils.BindableViewHolder; import me.grishka.appkit.views.UsableRecyclerView; +import me.grishka.houseclub.MainActivity; import me.grishka.houseclub.R; +import me.grishka.houseclub.VoiceService; +import me.grishka.houseclub.api.BaseResponse; import me.grishka.houseclub.api.ClubhouseSession; +import me.grishka.houseclub.api.methods.AudienceReply; +import me.grishka.houseclub.api.methods.GetFollowers; +import me.grishka.houseclub.api.methods.InviteToRoom; +import me.grishka.houseclub.api.methods.JoinChannel; +import me.grishka.houseclub.api.model.Channel; import me.grishka.houseclub.api.model.FullUser; public abstract class UserListFragment extends BaseRecyclerFragment{ @@ -140,9 +154,33 @@ public void clearImage(int index){ @Override public void onClick(){ - Bundle args=new Bundle(); - args.putInt("id", item.userId); - Nav.go(getActivity(), ProfileFragment.class, args); + if(getArguments().getString("type") == "invite_to_room"){ + System.out.println("USERPINGED"); + + new InviteToRoom(getArguments().getString("channel") , item.userId) + .setCallback(new Callback() { + @Override + public void onSuccess(BaseResponse result) { + + Toast.makeText(getActivity(), "User Pinged", Toast.LENGTH_SHORT).show(); + + } + @Override + public void onError(ErrorResponse error) { + + error.showToast(getContext()); + + } + }).exec(); + + + + }else { + Bundle args=new Bundle(); + args.putInt("id", item.userId); + Nav.go(getActivity(), ProfileFragment.class, args); + } + } } } diff --git a/Houseclub/src/main/res/drawable/ic_baseline_add_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_add_24.xml new file mode 100644 index 00000000..c7b1cb70 --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_add_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Houseclub/src/main/res/drawable/ic_baseline_calendar_today_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_calendar_today_24.xml new file mode 100644 index 00000000..8f05bd34 --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_calendar_today_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Houseclub/src/main/res/drawable/ic_baseline_mail_outline_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_mail_outline_24.xml new file mode 100644 index 00000000..9a40c829 --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_mail_outline_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Houseclub/src/main/res/drawable/ic_baseline_people_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_people_24.xml new file mode 100644 index 00000000..88a083ad --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_people_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Houseclub/src/main/res/drawable/ic_baseline_person_add_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_person_add_24.xml new file mode 100644 index 00000000..e918a98f --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_person_add_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Houseclub/src/main/res/drawable/ic_baseline_person_search_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_person_search_24.xml new file mode 100644 index 00000000..bac61cb9 --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_person_search_24.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/Houseclub/src/main/res/drawable/ic_baseline_search_24.xml b/Houseclub/src/main/res/drawable/ic_baseline_search_24.xml new file mode 100644 index 00000000..84683b00 --- /dev/null +++ b/Houseclub/src/main/res/drawable/ic_baseline_search_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Houseclub/src/main/res/layout/club.xml b/Houseclub/src/main/res/layout/club.xml new file mode 100644 index 00000000..0c0cef6f --- /dev/null +++ b/Houseclub/src/main/res/layout/club.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + +