1+ package awais .instagrabber .activities ;
2+
3+ import android .content .Intent ;
4+ import android .graphics .Bitmap ;
5+ import android .graphics .drawable .BitmapDrawable ;
6+ import android .graphics .drawable .Drawable ;
7+ import android .os .AsyncTask ;
8+ import android .os .Bundle ;
9+ import android .os .Environment ;
10+ import android .view .Menu ;
11+ import android .view .MenuItem ;
12+ import android .view .View ;
13+ import android .widget .Toast ;
14+
15+ import androidx .annotation .Nullable ;
16+ import androidx .fragment .app .FragmentManager ;
17+
18+ import com .bumptech .glide .Glide ;
19+ import com .bumptech .glide .RequestManager ;
20+ import com .bumptech .glide .load .DataSource ;
21+ import com .bumptech .glide .load .engine .GlideException ;
22+ import com .bumptech .glide .request .RequestListener ;
23+ import com .bumptech .glide .request .target .Target ;
24+
25+ import java .io .File ;
26+
27+ import awais .instagrabber .R ;
28+ import awais .instagrabber .asyncs .DownloadAsync ;
29+ import awais .instagrabber .asyncs .ProfilePictureFetcher ;
30+ import awais .instagrabber .databinding .ActivityProfilepicBinding ;
31+ import awais .instagrabber .interfaces .FetchListener ;
32+ import awais .instagrabber .models .HashtagModel ;
33+ import awais .instagrabber .models .LocationModel ;
34+ import awais .instagrabber .models .ProfileModel ;
35+ import awais .instagrabber .utils .Constants ;
36+ import awais .instagrabber .utils .Utils ;
37+
38+ public final class ProfilePicViewer extends BaseLanguageActivity {
39+ private ActivityProfilepicBinding profileBinding ;
40+ private ProfileModel profileModel ;
41+ private HashtagModel hashtagModel ;
42+ private LocationModel locationModel ;
43+ private MenuItem menuItemDownload ;
44+ private String profilePicUrl ;
45+ private FragmentManager fragmentManager ;
46+ private FetchListener <String > fetchListener ;
47+ private boolean errorHandled = false ;
48+ private boolean fallbackToProfile = false ;
49+ private boolean destroyed = false ;
50+
51+ @ Override
52+ protected void onCreate (@ Nullable final Bundle savedInstanceState ) {
53+ super .onCreate (savedInstanceState );
54+ profileBinding = ActivityProfilepicBinding .inflate (getLayoutInflater ());
55+ setContentView (profileBinding .getRoot ());
56+
57+ setSupportActionBar (profileBinding .toolbar .toolbar );
58+
59+ final Intent intent = getIntent ();
60+ if (intent == null || (!intent .hasExtra (Constants .EXTRAS_PROFILE ) && !intent .hasExtra (Constants .EXTRAS_HASHTAG ) && !intent .hasExtra (Constants .EXTRAS_LOCATION ))
61+ || ((profileModel = (ProfileModel ) intent .getSerializableExtra (Constants .EXTRAS_PROFILE )) == null
62+ && (hashtagModel = (HashtagModel ) intent .getSerializableExtra (Constants .EXTRAS_HASHTAG )) == null
63+ && (locationModel = (LocationModel ) intent .getSerializableExtra (Constants .EXTRAS_LOCATION )) == null )) {
64+ Utils .errorFinish (this );
65+ return ;
66+ }
67+
68+ fragmentManager = getSupportFragmentManager ();
69+
70+ final String id = hashtagModel != null ? hashtagModel .getId () : (locationModel != null ? locationModel .getId () : profileModel .getId ());
71+ final String username = hashtagModel != null ? hashtagModel .getName () : (locationModel != null ? locationModel .getName () : profileModel .getUsername ());
72+
73+ profileBinding .toolbar .toolbar .setTitle (username );
74+
75+ profileBinding .progressView .setVisibility (View .VISIBLE );
76+ profileBinding .imageViewer .setVisibility (View .VISIBLE );
77+
78+ profileBinding .imageViewer .setZoomable (true );
79+ profileBinding .imageViewer .setZoomTransitionDuration (420 );
80+ profileBinding .imageViewer .setMaximumScale (7.2f );
81+
82+ fetchListener = profileUrl -> {
83+ profilePicUrl = profileUrl ;
84+
85+ if (!fallbackToProfile && Utils .isEmpty (profilePicUrl )) {
86+ fallbackToProfile = true ;
87+ new ProfilePictureFetcher (username , id , fetchListener , profilePicUrl , (hashtagModel != null || locationModel != null )).executeOnExecutor (AsyncTask .THREAD_POOL_EXECUTOR );
88+ return ;
89+ }
90+
91+ if (errorHandled && fallbackToProfile || Utils .isEmpty (profilePicUrl ))
92+ profilePicUrl = hashtagModel != null ? hashtagModel .getSdProfilePic () : (locationModel != null ? locationModel .getSdProfilePic () : profileModel .getHdProfilePic ());
93+
94+ if (destroyed == true ) return ;
95+
96+ final RequestManager glideRequestManager = Glide .with (this );
97+
98+ glideRequestManager .load (profilePicUrl ).addListener (new RequestListener <Drawable >() {
99+ @ Override
100+ public boolean onLoadFailed (@ Nullable final GlideException e , final Object model , final Target <Drawable > target , final boolean isFirstResource ) {
101+ fallbackToProfile = true ;
102+ if (!errorHandled ) {
103+ errorHandled = true ;
104+ new ProfilePictureFetcher (username , id , fetchListener , profilePicUrl , (hashtagModel != null || locationModel != null ))
105+ .executeOnExecutor (AsyncTask .THREAD_POOL_EXECUTOR );
106+ } else {
107+ glideRequestManager .load (profilePicUrl ).into (profileBinding .imageViewer );
108+ showImageInfo ();
109+ }
110+ profileBinding .progressView .setVisibility (View .GONE );
111+ return false ;
112+ }
113+
114+ @ Override
115+ public boolean onResourceReady (final Drawable resource , final Object model , final Target <Drawable > target , final DataSource dataSource , final boolean isFirstResource ) {
116+ if (menuItemDownload != null ) menuItemDownload .setEnabled (true );
117+ showImageInfo ();
118+ profileBinding .progressView .setVisibility (View .GONE );
119+ return false ;
120+ }
121+
122+ private void showImageInfo () {
123+ final Drawable drawable = profileBinding .imageViewer .getDrawable ();
124+ if (drawable != null ) {
125+ final StringBuilder info = new StringBuilder (getString (R .string .profile_viewer_imageinfo , drawable .getIntrinsicWidth (), drawable .getIntrinsicHeight ()));
126+ if (drawable instanceof BitmapDrawable ) {
127+ final Bitmap bitmap = ((BitmapDrawable ) drawable ).getBitmap ();
128+ if (bitmap != null ) {
129+ final String colorDepthPrefix = getString (R .string .profile_viewer_colordepth_prefix );
130+ switch (bitmap .getConfig ()) {
131+ case ALPHA_8 :
132+ info .append (colorDepthPrefix ).append (" 8-bits(A)" );
133+ break ;
134+ case RGB_565 :
135+ info .append (colorDepthPrefix ).append (" 16-bits-A" );
136+ break ;
137+ case ARGB_4444 :
138+ info .append (colorDepthPrefix ).append (" 16-bits+A" );
139+ break ;
140+ case ARGB_8888 :
141+ info .append (colorDepthPrefix ).append (" 32-bits+A" );
142+ break ;
143+ case RGBA_F16 :
144+ info .append (colorDepthPrefix ).append (" 64-bits+A" );
145+ break ;
146+ case HARDWARE :
147+ info .append (colorDepthPrefix ).append (" auto" );
148+ break ;
149+ }
150+ }
151+ }
152+ profileBinding .imageInfo .setText (info );
153+ profileBinding .imageInfo .setVisibility (View .VISIBLE );
154+ }
155+ }
156+ }).into (profileBinding .imageViewer );
157+ };
158+
159+ new ProfilePictureFetcher (username , id , fetchListener , profilePicUrl , (hashtagModel != null || locationModel != null ))
160+ .executeOnExecutor (AsyncTask .THREAD_POOL_EXECUTOR );
161+ }
162+
163+ private void downloadProfilePicture () {
164+ int error = 0 ;
165+
166+ if (profileModel != null ) {
167+ final File dir = new File (Environment .getExternalStorageDirectory (), "Download" );
168+ if (dir .exists () || dir .mkdirs ()) {
169+
170+ final File saveFile = new File (dir , profileModel .getUsername () + '_' + System .currentTimeMillis ()
171+ + Utils .getExtensionFromModel (profilePicUrl , profileModel ));
172+
173+ new DownloadAsync (this ,
174+ profilePicUrl ,
175+ saveFile ,
176+ result -> {
177+ final int toastRes = result != null && result .exists () ?
178+ R .string .downloader_downloaded_in_folder : R .string .downloader_error_download_file ;
179+ Toast .makeText (this , toastRes , Toast .LENGTH_SHORT ).show ();
180+ }).setItems (null , profileModel .getUsername ()).executeOnExecutor (AsyncTask .THREAD_POOL_EXECUTOR );
181+ } else error = 1 ;
182+ } else error = 2 ;
183+
184+ if (error == 1 ) Toast .makeText (this , R .string .downloader_error_creating_folder , Toast .LENGTH_SHORT ).show ();
185+ else if (error == 2 ) Toast .makeText (this , R .string .downloader_unknown_error , Toast .LENGTH_SHORT ).show ();
186+ }
187+
188+ @ Override
189+ protected void onDestroy () {
190+ super .onDestroy ();
191+ getDelegate ().onDestroy ();
192+ destroyed = true ;
193+ }
194+
195+ @ Override
196+ public boolean onCreateOptionsMenu (final Menu menu ) {
197+ getMenuInflater ().inflate (R .menu .menu , menu );
198+
199+ final MenuItem .OnMenuItemClickListener menuItemClickListener = item -> {
200+ if (item == menuItemDownload ) {
201+ downloadProfilePicture ();
202+ }
203+ return true ;
204+ };
205+
206+ menu .findItem (R .id .action_search ).setVisible (false );
207+ menuItemDownload = menu .findItem (R .id .action_download );
208+ menuItemDownload .setVisible (true );
209+ menuItemDownload .setEnabled (false );
210+ menuItemDownload .setOnMenuItemClickListener (menuItemClickListener );
211+
212+ return true ;
213+ }
214+ }
0 commit comments