mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 14:53:59 +01:00 
			
		
		
		
	Merge remote-tracking branch 'refs/remotes/origin/master' into directNearbyUploads
This commit is contained in:
		
						commit
						e979d88aef
					
				
					 42 changed files with 879 additions and 288 deletions
				
			
		|  | @ -8,10 +8,18 @@ import butterknife.ButterKnife; | |||
| import fr.free.nrw.commons.theme.NavigationBaseActivity; | ||||
| import fr.free.nrw.commons.ui.widget.HtmlTextView; | ||||
| 
 | ||||
| /** | ||||
|  * Represents about screen of this app | ||||
|  */ | ||||
| public class AboutActivity extends NavigationBaseActivity { | ||||
|     @BindView(R.id.about_version) TextView versionText; | ||||
|     @BindView(R.id.about_license) HtmlTextView aboutLicenseText; | ||||
| 
 | ||||
|     /** | ||||
|      * This method helps in the creation About screen | ||||
|      * | ||||
|      * @param savedInstanceState Data bundle | ||||
|      */ | ||||
|     @Override | ||||
|     public void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|  |  | |||
|  | @ -49,16 +49,21 @@ public class CommonsApplication extends DaggerApplication { | |||
|     @Inject @Named("default_preferences") SharedPreferences defaultPrefs; | ||||
|     @Inject @Named("application_preferences") SharedPreferences applicationPrefs; | ||||
|     @Inject @Named("prefs") SharedPreferences otherPrefs; | ||||
| 
 | ||||
|      | ||||
|     public static final String DEFAULT_EDIT_SUMMARY = "Uploaded using Android Commons app"; | ||||
| 
 | ||||
|      | ||||
|     public static final String FEEDBACK_EMAIL = "commons-app-android@googlegroups.com"; | ||||
|      | ||||
|     public static final String LOGS_PRIVATE_EMAIL = "commons-app-android-private@googlegroups.com"; | ||||
|      | ||||
|     public static final String FEEDBACK_EMAIL_SUBJECT = "Commons Android App (%s) Feedback"; | ||||
| 
 | ||||
|      | ||||
|     private CommonsApplicationComponent component; | ||||
|     private RefWatcher refWatcher; | ||||
| 
 | ||||
|     /** | ||||
|      * Used to declare and initialize various components and dependencies | ||||
|      */ | ||||
|     @Override | ||||
|     public void onCreate() { | ||||
|         super.onCreate(); | ||||
|  | @ -80,23 +85,41 @@ public class CommonsApplication extends DaggerApplication { | |||
|         System.setProperty("in.yuvi.http.fluent.PROGRESS_TRIGGER_THRESHOLD", "3.0"); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Helps in setting up LeakCanary library | ||||
|      * @return instance of LeakCanary | ||||
|      */ | ||||
|     protected RefWatcher setupLeakCanary() { | ||||
|         if (LeakCanary.isInAnalyzerProcess(this)) { | ||||
|             return RefWatcher.DISABLED; | ||||
|         } | ||||
|         return LeakCanary.install(this); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|   /** | ||||
|      * Provides a way to get member refWatcher | ||||
|      * | ||||
|      * @param context Application context | ||||
|      * @return application member refWatcher | ||||
|      */ | ||||
|     public static RefWatcher getRefWatcher(Context context) { | ||||
|         CommonsApplication application = (CommonsApplication) context.getApplicationContext(); | ||||
|         return application.refWatcher; | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     /** | ||||
|     * Helps in injecting dependency library Dagger | ||||
|     * @return Dagger injector | ||||
|     */ | ||||
|     @Override | ||||
|      protected AndroidInjector<? extends DaggerApplication> applicationInjector() { | ||||
|     protected AndroidInjector<? extends DaggerApplication> applicationInjector() { | ||||
|         return injector(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * used to create injector of application component | ||||
|      * @return Application component of Dagger | ||||
|      */ | ||||
|     public CommonsApplicationComponent injector() { | ||||
|         if (component == null) { | ||||
|             component = DaggerCommonsApplicationComponent.builder() | ||||
|  | @ -106,6 +129,11 @@ public class CommonsApplication extends DaggerApplication { | |||
|         return component; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * clears data of current application | ||||
|      * @param context Application context | ||||
|      * @param logoutListener Implementation of interface LogoutListener | ||||
|      */ | ||||
|     public void clearApplicationData(Context context, LogoutListener logoutListener) { | ||||
|         File cacheDirectory = context.getCacheDir(); | ||||
|         File applicationDirectory = new File(cacheDirectory.getParent()); | ||||
|  | @ -145,6 +173,9 @@ public class CommonsApplication extends DaggerApplication { | |||
|         Contribution.Table.onDelete(db); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Interface used to get log-out events | ||||
|      */ | ||||
|     public interface LogoutListener { | ||||
|         void onLogoutComplete(); | ||||
|     } | ||||
|  |  | |||
|  | @ -2,6 +2,9 @@ package fr.free.nrw.commons; | |||
| 
 | ||||
| import android.support.annotation.Nullable; | ||||
| 
 | ||||
| /** | ||||
|  * represents Licence object | ||||
|  */ | ||||
| public class License { | ||||
|     private String key; | ||||
|     private String template; | ||||
|  | @ -56,6 +59,12 @@ public class License { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets the license URL | ||||
|      * | ||||
|      * @param language license language | ||||
|      * @return URL | ||||
|      */ | ||||
|     public @Nullable String getUrl(String language) { | ||||
|         if (url == null) { | ||||
|             return null; | ||||
|  |  | |||
|  | @ -13,10 +13,18 @@ import java.util.HashMap; | |||
| import java.util.Locale; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| /** | ||||
|  * Represents a list of Licenses | ||||
|  */ | ||||
| public class LicenseList { | ||||
|     private Map<String, License> licenses = new HashMap<>(); | ||||
|     private Resources res; | ||||
| 
 | ||||
|     /** | ||||
|      * Constructs new instance of LicenceList | ||||
|      * | ||||
|      * @param activity License activity | ||||
|      */ | ||||
|     public LicenseList(Activity activity) { | ||||
|         res = activity.getResources(); | ||||
|         XmlPullParser parser = res.getXml(R.xml.wikimedia_licenses); | ||||
|  | @ -31,14 +39,28 @@ public class LicenseList { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets a collection of licenses | ||||
|      * @return License values | ||||
|      */ | ||||
|     public Collection<License> values() { | ||||
|         return licenses.values(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets license | ||||
|      * @param key License key | ||||
|      * @return License that matches key | ||||
|      */ | ||||
|     public License get(String key) { | ||||
|         return licenses.get(key); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a license from template | ||||
|      * @param template License template | ||||
|      * @return null | ||||
|      */ | ||||
|     @Nullable | ||||
|     License licenseForTemplate(String template) { | ||||
|         String ucTemplate = new PageTitle(template).getDisplayText(); | ||||
|  | @ -50,6 +72,11 @@ public class LicenseList { | |||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets template name id | ||||
|      * @param template License template | ||||
|      * @return name id of template | ||||
|      */ | ||||
|     private String nameIdForTemplate(String template) { | ||||
|         // hack :D (converts dashes and periods to underscores) | ||||
|         // cc-by-sa-3.0 -> cc_by_sa_3_0 | ||||
|  | @ -57,6 +84,11 @@ public class LicenseList { | |||
|                 "_").replace(".", "_"); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets name of given template | ||||
|      * @param template License template | ||||
|      * @return name of template | ||||
|      */ | ||||
|     private String nameForTemplate(String template) { | ||||
|         int nameId = res.getIdentifier("fr.free.nrw.commons:string/" | ||||
|                 + nameIdForTemplate(template), null, null); | ||||
|  | @ -92,4 +124,4 @@ public class LicenseList { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -47,16 +47,35 @@ public class Media implements Parcelable { | |||
|     private HashMap<String, Object> tags = new HashMap<>(); | ||||
|     private @Nullable LatLng coordinates; | ||||
| 
 | ||||
|     /** | ||||
|      * Provides local constructor | ||||
|      */ | ||||
|     protected Media() { | ||||
|         this.categories = new ArrayList<>(); | ||||
|         this.descriptions = new HashMap<>(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Provides a minimal constructor | ||||
|      * | ||||
|      * @param filename Media filename | ||||
|      */ | ||||
|     public Media(String filename) { | ||||
|         this(); | ||||
|         this.filename = filename; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Provide Media constructor | ||||
|      * @param localUri Media URI | ||||
|      * @param imageUrl Media image URL | ||||
|      * @param filename Media filename | ||||
|      * @param description Media description | ||||
|      * @param dataLength Media date length | ||||
|      * @param dateCreated Media creation date | ||||
|      * @param dateUploaded Media date uploaded | ||||
|      * @param creator Media creator | ||||
|      */ | ||||
|     public Media(Uri localUri, String imageUrl, String filename, String description, | ||||
|                  long dataLength, Date dateCreated, @Nullable Date dateUploaded, String creator) { | ||||
|         this(); | ||||
|  | @ -90,19 +109,33 @@ public class Media implements Parcelable { | |||
|         descriptions = in.readHashMap(ClassLoader.getSystemClassLoader()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets tag of media | ||||
|      * @param key Media key | ||||
|      * @return Media tag | ||||
|      */ | ||||
|     public Object getTag(String key) { | ||||
|         return tags.get(key); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Modifies( or creates a) tag of media | ||||
|      * @param key Media key | ||||
|      * @param value Media value | ||||
|      */ | ||||
|     public void setTag(String key, Object value) { | ||||
|         tags.put(key, value); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets media display title | ||||
|      * @return Media title | ||||
|      */ | ||||
|     public String getDisplayTitle() { | ||||
|         if (filename == null) { | ||||
|             return ""; | ||||
|         } | ||||
|         // FIXME: Gross hack bercause my regex skills suck maybe or I am too lazy who knows | ||||
|         // FIXME: Gross hack because my regex skills suck maybe or I am too lazy who knows | ||||
|         String title = getFilePageTitle().getDisplayText().replaceFirst("^File:", ""); | ||||
|         Matcher matcher = displayTitlePattern.matcher(title); | ||||
|         if (matcher.matches()) { | ||||
|  | @ -112,14 +145,27 @@ public class Media implements Parcelable { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets file page title | ||||
|      * @return New media page title | ||||
|      */ | ||||
|     public PageTitle getFilePageTitle() { | ||||
|         return new PageTitle("File:" + getFilename().replaceFirst("^File:", "")); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets local URI | ||||
|      * @return Media local URI | ||||
|      */ | ||||
|     public Uri getLocalUri() { | ||||
|         return localUri; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets image URL | ||||
|      * can be null. | ||||
|      * @return Image URL | ||||
|      */ | ||||
|     @Nullable | ||||
|     public String getImageUrl() { | ||||
|         if (imageUrl == null && this.getFilename() != null) { | ||||
|  | @ -304,6 +350,10 @@ public class Media implements Parcelable { | |||
|         this.categories.addAll(categories); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Modifies (or sets) media descriptions | ||||
|      * @param descriptions Media descriptions | ||||
|      */ | ||||
|     void setDescriptions(Map<String, String> descriptions) { | ||||
|         for (String key : this.descriptions.keySet()) { | ||||
|             this.descriptions.remove(key); | ||||
|  | @ -313,6 +363,11 @@ public class Media implements Parcelable { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets media description in preferred language | ||||
|      * @param preferredLanguage Language preferred | ||||
|      * @return Description in preferred language | ||||
|      */ | ||||
|     public String getDescription(String preferredLanguage) { | ||||
|         if (descriptions.containsKey(preferredLanguage)) { | ||||
|             // See if the requested language is there. | ||||
|  | @ -329,11 +384,21 @@ public class Media implements Parcelable { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Method of Parcelable interface | ||||
|      * @return zero | ||||
|      */ | ||||
|     @Override | ||||
|     public int describeContents() { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a way to transfer information between two or more | ||||
|      * activities. | ||||
|      * @param parcel Instance of Parcel | ||||
|      * @param flags Parcel flag | ||||
|      */ | ||||
|     @Override | ||||
|     public void writeToParcel(Parcel parcel, int flags) { | ||||
|         parcel.writeParcelable(localUri, flags); | ||||
|  |  | |||
|  | @ -37,12 +37,23 @@ public class Utils { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Creates an URL for thumbnail | ||||
|      * | ||||
|      * @param filename Thumbnail file name | ||||
|      * @return URL of thumbnail | ||||
|      */ | ||||
|     public static String makeThumbBaseUrl(@NonNull String filename) { | ||||
|         String name = new PageTitle(filename).getPrefixedText(); | ||||
|         String sha = new String(Hex.encodeHex(DigestUtils.md5(name))); | ||||
|         return String.format("%s/%s/%s/%s", BuildConfig.IMAGE_URL_BASE, sha.substring(0, 1), sha.substring(0, 2), urlEncode(name)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * URL Encode an URL in UTF-8 format | ||||
|      * @param url Unformatted URL | ||||
|      * @return Encoded URL | ||||
|      */ | ||||
|     public static String urlEncode(String url) { | ||||
|         try { | ||||
|             return URLEncoder.encode(url, "utf-8"); | ||||
|  | @ -61,6 +72,11 @@ public class Utils { | |||
|         return string.substring(0, 1).toUpperCase(Locale.getDefault()) + string.substring(1); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Generates licence name with given ID | ||||
|      * @param license License ID | ||||
|      * @return Name of license | ||||
|      */ | ||||
|     public static int licenseNameFor(String license) { | ||||
|         switch (license) { | ||||
|             case Prefs.Licenses.CC_BY_3: | ||||
|  | @ -81,6 +97,12 @@ public class Utils { | |||
|         throw new RuntimeException("Unrecognized license value: " + license); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fixing incorrect extension | ||||
|      * @param title File name | ||||
|      * @param extension Correct extension | ||||
|      * @return File with correct extension | ||||
|      */ | ||||
|     public static String fixExtension(String title, String extension) { | ||||
|         Pattern jpegPattern = Pattern.compile("\\.jpeg$", Pattern.CASE_INSENSITIVE); | ||||
| 
 | ||||
|  | @ -96,6 +118,11 @@ public class Utils { | |||
|         return title; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Tells whether dark theme is active or not | ||||
|      * @param context Activity context | ||||
|      * @return The state of dark theme | ||||
|      */ | ||||
|     public static boolean isDarkTheme(Context context) { | ||||
|         return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("theme", false); | ||||
|     } | ||||
|  |  | |||
|  | @ -18,6 +18,11 @@ public class WelcomeActivity extends BaseActivity { | |||
| 
 | ||||
|     private WelcomePagerAdapter adapter = new WelcomePagerAdapter(); | ||||
| 
 | ||||
|     /** | ||||
|      * Initialises exiting fields and dependencies | ||||
|      * | ||||
|      * @param savedInstanceState WelcomeActivity bundled data | ||||
|      */ | ||||
|     @Override | ||||
|     public void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|  | @ -30,12 +35,20 @@ public class WelcomeActivity extends BaseActivity { | |||
|         adapter.setCallback(this::finish); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * References WelcomePageAdapter to null before the activity is destroyed | ||||
|      */ | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         adapter.setCallback(null); | ||||
|         super.onDestroy(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Creates a way to change current activity to WelcomeActivity | ||||
|      * | ||||
|      * @param context Activity context | ||||
|      */ | ||||
|     public static void startYourself(Context context) { | ||||
|         Intent welcomeIntent = new Intent(context, WelcomeActivity.class); | ||||
|         context.startActivity(welcomeIntent); | ||||
|  |  | |||
|  | @ -10,13 +10,6 @@ import butterknife.ButterKnife; | |||
| import butterknife.OnClick; | ||||
| 
 | ||||
| public class WelcomePagerAdapter extends PagerAdapter { | ||||
|     private static final int PAGE_FINAL = 4; | ||||
|     private Callback callback; | ||||
| 
 | ||||
|     public interface Callback { | ||||
|         void onYesClicked(); | ||||
|     } | ||||
| 
 | ||||
|     static final int[] PAGE_LAYOUTS = new int[]{ | ||||
|             R.layout.welcome_wikipedia, | ||||
|             R.layout.welcome_do_upload, | ||||
|  | @ -24,16 +17,34 @@ public class WelcomePagerAdapter extends PagerAdapter { | |||
|             R.layout.welcome_image_details, | ||||
|             R.layout.welcome_final | ||||
|     }; | ||||
|     private static final int PAGE_FINAL = 4; | ||||
|     private Callback callback; | ||||
| 
 | ||||
|     /** | ||||
|      * Changes callback to provided one | ||||
|      * | ||||
|      * @param callback New callback | ||||
|      *                 it can be null. | ||||
|      */ | ||||
|     public void setCallback(@Nullable Callback callback) { | ||||
|         this.callback = callback; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets total number of layouts | ||||
|      * @return Number of layouts | ||||
|      */ | ||||
|     @Override | ||||
|     public int getCount() { | ||||
|         return PAGE_LAYOUTS.length; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Compares given view with provided object | ||||
|      * @param view Adapter view | ||||
|      * @param object Adapter object | ||||
|      * @return Equality between view and object | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean isViewFromObject(View view, Object object) { | ||||
|         return (view == object); | ||||
|  | @ -52,16 +63,29 @@ public class WelcomePagerAdapter extends PagerAdapter { | |||
|         return layout; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Provides a way to remove an item from container | ||||
|      * @param container Adapter view group container | ||||
|      * @param position Index of item | ||||
|      * @param obj Adapter object | ||||
|      */ | ||||
|     @Override | ||||
|     public void destroyItem(ViewGroup container, int position, Object obj) { | ||||
|         container.removeView((View) obj); | ||||
|     } | ||||
| 
 | ||||
|     public interface Callback { | ||||
|         void onYesClicked(); | ||||
|     } | ||||
| 
 | ||||
|     class ViewHolder { | ||||
|         ViewHolder(View view) { | ||||
|             ButterKnife.bind(this, view); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Triggers on click callback on button click | ||||
|          */ | ||||
|         @OnClick(R.id.welcomeYesButton) | ||||
|         void onClicked() { | ||||
|             if (callback != null) { | ||||
|  |  | |||
|  | @ -14,6 +14,9 @@ import java.util.Date; | |||
| 
 | ||||
| import fr.free.nrw.commons.category.CategoryContentProvider; | ||||
| 
 | ||||
| /** | ||||
|  * Represents a category | ||||
|  */ | ||||
| public class Category { | ||||
|     private Uri contentUri; | ||||
| 
 | ||||
|  | @ -22,36 +25,72 @@ public class Category { | |||
|     private int timesUsed; | ||||
| 
 | ||||
|     // Getters/setters | ||||
|     /** | ||||
|      * Gets name | ||||
|      * | ||||
|      * @return name | ||||
|      */ | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Modifies name | ||||
|      * | ||||
|      * @param name Category name | ||||
|      */ | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets last used date | ||||
|      * | ||||
|      * @return Last used date | ||||
|      */ | ||||
|     private Date getLastUsed() { | ||||
|         // warning: Date objects are mutable. | ||||
|         return (Date)lastUsed.clone(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Modifies last used date | ||||
|      * | ||||
|      * @param lastUsed Category date | ||||
|      */ | ||||
|     public void setLastUsed(Date lastUsed) { | ||||
|         // warning: Date objects are mutable. | ||||
|         this.lastUsed = (Date)lastUsed.clone(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Generates new last used date | ||||
|      */ | ||||
|     private void touch() { | ||||
|         lastUsed = new Date(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets no. of times the category is used | ||||
|      * | ||||
|      * @return no. of times used | ||||
|      */ | ||||
|     private int getTimesUsed() { | ||||
|         return timesUsed; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Modifies no. of times used | ||||
|      * | ||||
|      * @param timesUsed Category used times | ||||
|      */ | ||||
|     public void setTimesUsed(int timesUsed) { | ||||
|         this.timesUsed = timesUsed; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Increments timesUsed by 1 and sets last used date as now. | ||||
|      */ | ||||
|     public void incTimesUsed() { | ||||
|         timesUsed++; | ||||
|         touch(); | ||||
|  | @ -75,6 +114,11 @@ public class Category { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets content values | ||||
|      * | ||||
|      * @return Content values | ||||
|      */ | ||||
|     private ContentValues toContentValues() { | ||||
|         ContentValues cv = new ContentValues(); | ||||
|         cv.put(Table.COLUMN_NAME, getName()); | ||||
|  | @ -83,6 +127,11 @@ public class Category { | |||
|         return cv; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets category from cursor | ||||
|      * @param cursor Category cursor | ||||
|      * @return Category from cursor | ||||
|      */ | ||||
|     private static Category fromCursor(Cursor cursor) { | ||||
|         // Hardcoding column positions! | ||||
|         Category c = new Category(); | ||||
|  | @ -175,15 +224,30 @@ public class Category { | |||
|                 + COLUMN_TIMES_USED + " INTEGER" | ||||
|                 + ");"; | ||||
| 
 | ||||
|         /** | ||||
|          * Creates new table with provided SQLite database | ||||
|          * | ||||
|          * @param db Category database | ||||
|          */ | ||||
|         public static void onCreate(SQLiteDatabase db) { | ||||
|             db.execSQL(CREATE_TABLE_STATEMENT); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Deletes existing table | ||||
|          * @param db Category database | ||||
|          */ | ||||
|         public static void onDelete(SQLiteDatabase db) { | ||||
|             db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); | ||||
|             onCreate(db); | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Updates given database | ||||
|          * @param db Category database | ||||
|          * @param from Exiting category id | ||||
|          * @param to New category id | ||||
|          */ | ||||
|         public static void onUpdate(SQLiteDatabase db, int from, int to) { | ||||
|             if (from == to) { | ||||
|                 return; | ||||
|  | @ -209,4 +273,4 @@ public class Category { | |||
|         } | ||||
|     } | ||||
|     //endregion | ||||
| } | ||||
| } | ||||
|  | @ -134,4 +134,4 @@ public class LatLng { | |||
|     public Uri getGmmIntentUri() { | ||||
|         return Uri.parse("geo:0,0?q=" + latitude + "," + longitude); | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -384,7 +384,7 @@ public class MediaDetailFragment extends DaggerFragment { | |||
|     private void openMap(LatLng coordinates) { | ||||
|         //Open map app at given position | ||||
|         Uri gmmIntentUri = Uri.parse( | ||||
|                 "geo:0,0?q=" + coordinates.getLatitude() + "," + coordinates.getLatitude()); | ||||
|                 "geo:0,0?q=" + coordinates.getLatitude() + "," + coordinates.getLongitude()); | ||||
|         Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); | ||||
| 
 | ||||
|         if (mapIntent.resolveActivity(getActivity().getPackageManager()) != null) { | ||||
|  |  | |||
|  | @ -22,6 +22,14 @@ public class LogBuilder { | |||
|     private final String schema; | ||||
|     private final SharedPreferences prefs; | ||||
| 
 | ||||
|     /** | ||||
|      * Main constructor of LogBuilder | ||||
|      * | ||||
|      * @param schema   Log schema | ||||
|      * @param revision Log revision | ||||
|      * @param mwApi    Wiki media API instance | ||||
|      * @param prefs    Instance of SharedPreferences | ||||
|      */ | ||||
|     LogBuilder(String schema, long revision, MediaWikiApi mwApi, SharedPreferences prefs) { | ||||
|         this.prefs = prefs; | ||||
|         this.data = new JSONObject(); | ||||
|  | @ -30,6 +38,12 @@ public class LogBuilder { | |||
|         this.mwApi = mwApi; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Adds data to preferences | ||||
|      * @param key Log key | ||||
|      * @param value Log object value | ||||
|      * @return LogBuilder | ||||
|      */ | ||||
|     public LogBuilder param(String key, Object value) { | ||||
|         try { | ||||
|             data.put(key, value); | ||||
|  | @ -39,6 +53,10 @@ public class LogBuilder { | |||
|         return this; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Encodes JSON object to URL | ||||
|      * @return URL to JSON object | ||||
|      */ | ||||
|     URL toUrl() { | ||||
|         JSONObject fullData = new JSONObject(); | ||||
|         try { | ||||
|  | @ -65,7 +83,7 @@ public class LogBuilder { | |||
|         LogTask logTask = new LogTask(mwApi); | ||||
|         logTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, this); | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     public void log() { | ||||
|         log(false); | ||||
|     } | ||||
|  |  | |||
|  | @ -6,10 +6,20 @@ class LogTask extends AsyncTask<LogBuilder, Void, Boolean> { | |||
| 
 | ||||
|     private final MediaWikiApi mwApi; | ||||
| 
 | ||||
|     /** | ||||
|      * Main constructor of LogTask | ||||
|      * | ||||
|      * @param mwApi Media wiki API instance | ||||
|      */ | ||||
|     public LogTask(MediaWikiApi mwApi) { | ||||
|         this.mwApi = mwApi; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Logs events in background | ||||
|      * @param logBuilders LogBuilder instance | ||||
|      * @return Background success state ( TRUE or FALSE ) | ||||
|      */ | ||||
|     @Override | ||||
|     protected Boolean doInBackground(LogBuilder... logBuilders) { | ||||
|         return mwApi.logEvents(logBuilders); | ||||
|  |  | |||
|  | @ -4,15 +4,29 @@ public class MediaResult { | |||
|     private final String wikiSource; | ||||
|     private final String parseTreeXmlSource; | ||||
| 
 | ||||
|     /** | ||||
|      * Full-fledged constructor of MediaResult | ||||
|      * | ||||
|      * @param wikiSource         Media wiki source | ||||
|      * @param parseTreeXmlSource Media tree parsed in XML | ||||
|      */ | ||||
|     MediaResult(String wikiSource, String parseTreeXmlSource) { | ||||
|         this.wikiSource = wikiSource; | ||||
|         this.parseTreeXmlSource = parseTreeXmlSource; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets wiki source | ||||
|      * @return Wiki source | ||||
|      */ | ||||
|     public String getWikiSource() { | ||||
|         return wikiSource; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets tree parsed in XML | ||||
|      * @return XML parsed tree | ||||
|      */ | ||||
|     public String getParseTreeXmlSource() { | ||||
|         return parseTreeXmlSource; | ||||
|     } | ||||
|  |  | |||
|  | @ -9,11 +9,24 @@ public class UploadResult { | |||
|     private String imageUrl; | ||||
|     private String canonicalFilename; | ||||
| 
 | ||||
|     /** | ||||
|      * Minimal constructor | ||||
|      * | ||||
|      * @param resultStatus Upload result status | ||||
|      * @param errorCode    Upload error code | ||||
|      */ | ||||
|     UploadResult(String resultStatus, String errorCode) { | ||||
|         this.resultStatus = resultStatus; | ||||
|         this.errorCode = errorCode; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Full-fledged constructor | ||||
|      * @param resultStatus Upload result status | ||||
|      * @param dateUploaded Uploaded date | ||||
|      * @param canonicalFilename Uploaded file name | ||||
|      * @param imageUrl Uploaded image file name | ||||
|      */ | ||||
|     UploadResult(String resultStatus, Date dateUploaded, String canonicalFilename, String imageUrl) { | ||||
|         this.resultStatus = resultStatus; | ||||
|         this.dateUploaded = dateUploaded; | ||||
|  | @ -21,22 +34,42 @@ public class UploadResult { | |||
|         this.imageUrl = imageUrl; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets uploaded date | ||||
|      * @return Upload date | ||||
|      */ | ||||
|     public Date getDateUploaded() { | ||||
|         return dateUploaded; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets image url | ||||
|      * @return Uploaded image url | ||||
|      */ | ||||
|     public String getImageUrl() { | ||||
|         return imageUrl; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets canonical file name | ||||
|      * @return Uploaded file name | ||||
|      */ | ||||
|     public String getCanonicalFilename() { | ||||
|         return canonicalFilename; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets upload error code | ||||
|      * @return Error code | ||||
|      */ | ||||
|     public String getErrorCode() { | ||||
|         return errorCode; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets upload result status | ||||
|      * @return Upload result status | ||||
|      */ | ||||
|     public String getResultStatus() { | ||||
|         return resultStatus; | ||||
|     } | ||||
|  |  | |||
|  | @ -1,55 +1,70 @@ | |||
| package fr.free.nrw.commons.settings; | ||||
| 
 | ||||
| import android.os.Bundle; | ||||
| import android.preference.PreferenceManager; | ||||
| import android.support.v7.app.AppCompatDelegate; | ||||
| import android.view.MenuItem; | ||||
| 
 | ||||
| import butterknife.ButterKnife; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.theme.NavigationBaseActivity; | ||||
| 
 | ||||
| public class SettingsActivity extends NavigationBaseActivity { | ||||
|     private AppCompatDelegate settingsDelegate; | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         // Check prefs on every activity starts | ||||
|         if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("theme",false)) { | ||||
|             setTheme(R.style.DarkAppTheme); | ||||
|         } else { | ||||
|             setTheme(R.style.LightAppTheme); | ||||
|         } | ||||
| 
 | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_settings); | ||||
| 
 | ||||
|         ButterKnife.bind(this); | ||||
|         initDrawer(); | ||||
|     } | ||||
| 
 | ||||
|     // Get an action bar | ||||
|     @Override | ||||
|     protected void onPostCreate(Bundle savedInstanceState) { | ||||
|         super.onPostCreate(savedInstanceState); | ||||
|         if (settingsDelegate == null) { | ||||
|             settingsDelegate = AppCompatDelegate.create(this, null); | ||||
|         } | ||||
|         settingsDelegate.onPostCreate(savedInstanceState); | ||||
| 
 | ||||
|         //Get an up button | ||||
|         //settingsDelegate.getSupportActionBar().setDisplayHomeAsUpEnabled(true); | ||||
|     } | ||||
| 
 | ||||
|     //Handle action-bar clicks | ||||
|     @Override | ||||
|     public boolean onOptionsItemSelected(MenuItem item) { | ||||
|         switch (item.getItemId()) { | ||||
|             case android.R.id.home: | ||||
|                 finish(); | ||||
|                 return true; | ||||
|             default: | ||||
|                 return super.onOptionsItemSelected(item); | ||||
|         } | ||||
|     } | ||||
| package fr.free.nrw.commons.settings; | ||||
| 
 | ||||
| import android.os.Bundle; | ||||
| import android.preference.PreferenceManager; | ||||
| import android.support.v7.app.AppCompatDelegate; | ||||
| import android.view.MenuItem; | ||||
| 
 | ||||
| import butterknife.ButterKnife; | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.theme.NavigationBaseActivity; | ||||
| 
 | ||||
| /** | ||||
|  * allows the user to change the settings | ||||
|  */ | ||||
| public class SettingsActivity extends NavigationBaseActivity { | ||||
|     private AppCompatDelegate settingsDelegate; | ||||
| 
 | ||||
|     /** | ||||
|      * to be called when the activity starts | ||||
|      * @param savedInstanceState the previously saved state | ||||
|      */ | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         // Check prefs on every activity starts | ||||
|         if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("theme",false)) { | ||||
|             setTheme(R.style.DarkAppTheme); | ||||
|         } else { | ||||
|             setTheme(R.style.LightAppTheme); | ||||
|         } | ||||
| 
 | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_settings); | ||||
| 
 | ||||
|         ButterKnife.bind(this); | ||||
|         initDrawer(); | ||||
|     } | ||||
| 
 | ||||
|     // Get an action bar | ||||
|     /** | ||||
|      * takes care of actions taken after the creation has happened | ||||
|      * @param savedInstanceState the saved state | ||||
|      */ | ||||
|     @Override | ||||
|     protected void onPostCreate(Bundle savedInstanceState) { | ||||
|         super.onPostCreate(savedInstanceState); | ||||
|         if (settingsDelegate == null) { | ||||
|             settingsDelegate = AppCompatDelegate.create(this, null); | ||||
|         } | ||||
|         settingsDelegate.onPostCreate(savedInstanceState); | ||||
| 
 | ||||
|         //Get an up button | ||||
|         //settingsDelegate.getSupportActionBar().setDisplayHomeAsUpEnabled(true); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Handle action-bar clicks | ||||
|      * @param item the selected item | ||||
|      * @return true on success, false on failure | ||||
|      */ | ||||
|     @Override | ||||
|     public boolean onOptionsItemSelected(MenuItem item) { | ||||
|         switch (item.getItemId()) { | ||||
|             case android.R.id.home: | ||||
|                 finish(); | ||||
|                 return true; | ||||
|             default: | ||||
|                 return super.onOptionsItemSelected(item); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,73 +1,96 @@ | |||
| package fr.free.nrw.commons.ui.widget; | ||||
| 
 | ||||
| /** | ||||
|  * Created by mikel on 07/08/2017. | ||||
|  */ | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.v4.view.ViewCompat; | ||||
| import android.support.v7.widget.AppCompatDrawableManager; | ||||
| import android.support.v7.widget.AppCompatTextView; | ||||
| import android.util.AttributeSet; | ||||
| 
 | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.utils.UiUtils; | ||||
| 
 | ||||
| public class CompatTextView extends AppCompatTextView { | ||||
|     public CompatTextView(Context context) { | ||||
|         super(context); | ||||
|         init(null); | ||||
|     } | ||||
| 
 | ||||
|     public CompatTextView(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|         init(attrs); | ||||
|     } | ||||
| 
 | ||||
|     public CompatTextView(Context context, AttributeSet attrs, int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|         init(attrs); | ||||
|     } | ||||
| 
 | ||||
|     private void init(@Nullable AttributeSet attrs) { | ||||
|         if (attrs != null) { | ||||
|             Context context = getContext(); | ||||
|             TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CompatTextView); | ||||
| 
 | ||||
|             // Obtain DrawableManager used to pull Drawables safely, and check if we're in RTL | ||||
|             AppCompatDrawableManager dm = AppCompatDrawableManager.get(); | ||||
|             boolean rtl = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL; | ||||
| 
 | ||||
|             // Grab the compat drawable padding from the XML | ||||
|             float drawablePadding = a.getDimension(R.styleable.CompatTextView_drawablePadding, 0); | ||||
| 
 | ||||
|             // Grab the compat drawable resources from the XML | ||||
|             int startDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableStart, 0); | ||||
|             int topDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableTop, 0); | ||||
|             int endDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableEnd, 0); | ||||
|             int bottomDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableBottom, 0); | ||||
| 
 | ||||
|             // Load the used drawables, fall back to whatever was set in an "android:" | ||||
|             Drawable[] currentDrawables = getCompoundDrawables(); | ||||
|             Drawable left = startDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, startDrawableRes) : currentDrawables[0]; | ||||
|             Drawable right = endDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, endDrawableRes) : currentDrawables[1]; | ||||
|             Drawable top = topDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, topDrawableRes) : currentDrawables[2]; | ||||
|             Drawable bottom = bottomDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, bottomDrawableRes) : currentDrawables[3]; | ||||
| 
 | ||||
|             // Account for RTL and apply the compound Drawables | ||||
|             Drawable start = rtl ? right : left; | ||||
|             Drawable end = rtl ? left : right; | ||||
|             setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom); | ||||
|             setCompoundDrawablePadding((int) UiUtils.convertDpToPixel(drawablePadding, getContext())); | ||||
| 
 | ||||
|             a.recycle(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| package fr.free.nrw.commons.ui.widget; | ||||
| 
 | ||||
| /** | ||||
|  * Created by mikel on 07/08/2017. | ||||
|  */ | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.v4.view.ViewCompat; | ||||
| import android.support.v7.widget.AppCompatDrawableManager; | ||||
| import android.support.v7.widget.AppCompatTextView; | ||||
| import android.util.AttributeSet; | ||||
| 
 | ||||
| import fr.free.nrw.commons.R; | ||||
| import fr.free.nrw.commons.utils.UiUtils; | ||||
| 
 | ||||
| /** | ||||
|  * a text view compatible with older versions of the platform | ||||
|  */ | ||||
| public class CompatTextView extends AppCompatTextView { | ||||
| 	 | ||||
|     /** | ||||
|      * Constructs a new instance of CompatTextView | ||||
|      * @param context the view context | ||||
|      */ | ||||
|     public CompatTextView(Context context) { | ||||
|         super(context); | ||||
|         init(null); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Constructs a new instance of CompatTextView | ||||
|      * @param context the view context | ||||
|      * @param attrs the set of attributes for the view | ||||
|      */ | ||||
|     public CompatTextView(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|         init(attrs); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Constructs a new instance of CompatTextView | ||||
|      * @param context | ||||
|      * @param attrs | ||||
|      * @param defStyleAttr | ||||
|      */ | ||||
|     public CompatTextView(Context context, AttributeSet attrs, int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|         init(attrs); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * initializes the view | ||||
|      * @param attrs the attribute set of the view, which can be null | ||||
|      */ | ||||
|     private void init(@Nullable AttributeSet attrs) { | ||||
|         if (attrs != null) { | ||||
|             Context context = getContext(); | ||||
|             TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CompatTextView); | ||||
| 
 | ||||
|             // Obtain DrawableManager used to pull Drawables safely, and check if we're in RTL | ||||
|             AppCompatDrawableManager dm = AppCompatDrawableManager.get(); | ||||
|             boolean rtl = ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL; | ||||
| 
 | ||||
|             // Grab the compat drawable padding from the XML | ||||
|             float drawablePadding = a.getDimension(R.styleable.CompatTextView_drawablePadding, 0); | ||||
| 
 | ||||
|             // Grab the compat drawable resources from the XML | ||||
|             int startDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableStart, 0); | ||||
|             int topDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableTop, 0); | ||||
|             int endDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableEnd, 0); | ||||
|             int bottomDrawableRes = a.getResourceId(R.styleable.CompatTextView_drawableBottom, 0); | ||||
| 
 | ||||
|             // Load the used drawables, fall back to whatever was set in an "android:" | ||||
|             Drawable[] currentDrawables = getCompoundDrawables(); | ||||
|             Drawable left = startDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, startDrawableRes) : currentDrawables[0]; | ||||
|             Drawable right = endDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, endDrawableRes) : currentDrawables[1]; | ||||
|             Drawable top = topDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, topDrawableRes) : currentDrawables[2]; | ||||
|             Drawable bottom = bottomDrawableRes != 0 | ||||
|                     ? dm.getDrawable(context, bottomDrawableRes) : currentDrawables[3]; | ||||
| 
 | ||||
|             // Account for RTL and apply the compound Drawables | ||||
|             Drawable start = rtl ? right : left; | ||||
|             Drawable end = rtl ? left : right; | ||||
|             setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom); | ||||
|             setCompoundDrawablePadding((int) UiUtils.convertDpToPixel(drawablePadding, getContext())); | ||||
| 
 | ||||
|             a.recycle(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,42 +1,51 @@ | |||
| package fr.free.nrw.commons.ui.widget; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.os.Build; | ||||
| import android.support.v7.widget.AppCompatTextView; | ||||
| import android.text.Html; | ||||
| import android.text.Spanned; | ||||
| import android.text.method.LinkMovementMethod; | ||||
| import android.util.AttributeSet; | ||||
| 
 | ||||
| /** | ||||
|  * An {@link AppCompatTextView} which formats the text to HTML displayable text and makes any | ||||
|  * links clickable. | ||||
|  */ | ||||
| public class HtmlTextView extends AppCompatTextView { | ||||
| 
 | ||||
|     public HtmlTextView(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
| 
 | ||||
|         setMovementMethod(LinkMovementMethod.getInstance()); | ||||
|         setText(fromHtml(getText().toString())); | ||||
|     } | ||||
| 
 | ||||
|     public void setHtmlText(String newText) { | ||||
|         setText(fromHtml(newText)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fix Html.fromHtml is deprecated problem | ||||
|      * | ||||
|      * @param source provided Html string | ||||
|      * @return returned Spanned of appropriate method according to version check | ||||
|      */ | ||||
|     private static Spanned fromHtml(String source) { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|             return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY); | ||||
|         } else { | ||||
|             //noinspection deprecation | ||||
|             return Html.fromHtml(source); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| package fr.free.nrw.commons.ui.widget; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.os.Build; | ||||
| import android.support.v7.widget.AppCompatTextView; | ||||
| import android.text.Html; | ||||
| import android.text.Spanned; | ||||
| import android.text.method.LinkMovementMethod; | ||||
| import android.util.AttributeSet; | ||||
| 
 | ||||
| /** | ||||
|  * An {@link AppCompatTextView} which formats the text to HTML displayable text and makes any | ||||
|  * links clickable. | ||||
|  */ | ||||
| public class HtmlTextView extends AppCompatTextView { | ||||
| 
 | ||||
|     /** | ||||
|      * Constructs a new instance of HtmlTextView | ||||
|      * @param context the context of the view | ||||
|      * @param attrs the set of attributes for the view | ||||
|      */ | ||||
|     public HtmlTextView(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
| 
 | ||||
|         setMovementMethod(LinkMovementMethod.getInstance()); | ||||
|         setText(fromHtml(getText().toString())); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Sets the text to be displayed | ||||
|      * @param newText the text to be displayed | ||||
|      */ | ||||
|     public void setHtmlText(String newText) { | ||||
|         setText(fromHtml(newText)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fix Html.fromHtml is deprecated problem | ||||
|      * | ||||
|      * @param source provided Html string | ||||
|      * @return returned Spanned of appropriate method according to version check | ||||
|      */ | ||||
|     private static Spanned fromHtml(String source) { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|             return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY); | ||||
|         } else { | ||||
|             //noinspection deprecation | ||||
|             return Html.fromHtml(source); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1,46 +1,69 @@ | |||
| package fr.free.nrw.commons.ui.widget; | ||||
| 
 | ||||
| import android.app.Dialog; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.drawable.ColorDrawable; | ||||
| import android.os.Bundle; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.v4.app.DialogFragment; | ||||
| import android.view.Gravity; | ||||
| import android.view.View; | ||||
| import android.view.Window; | ||||
| import android.view.WindowManager; | ||||
| 
 | ||||
| public abstract class OverlayDialog extends DialogFragment { | ||||
| 
 | ||||
|     @Override | ||||
|     public void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setStyle(STYLE_NO_FRAME, android.R.style.Theme_Holo_Light); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void onViewCreated(View view, Bundle savedInstanceState) { | ||||
|         setDialogLayoutToFullScreen(); | ||||
|         super.onViewCreated(view, savedInstanceState); | ||||
|     } | ||||
| 
 | ||||
|     private void setDialogLayoutToFullScreen() { | ||||
|         Window window = getDialog().getWindow(); | ||||
|         WindowManager.LayoutParams wlp = window.getAttributes(); | ||||
|         window.requestFeature(Window.FEATURE_NO_TITLE); | ||||
|         wlp.gravity = Gravity.BOTTOM; | ||||
|         wlp.width = WindowManager.LayoutParams.MATCH_PARENT; | ||||
|         wlp.height = WindowManager.LayoutParams.MATCH_PARENT; | ||||
|         window.setAttributes(wlp); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public Dialog onCreateDialog(Bundle savedInstanceState) { | ||||
|         Dialog dialog = super.onCreateDialog(savedInstanceState); | ||||
|         Window window = dialog.getWindow(); | ||||
|         window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); | ||||
|         return dialog; | ||||
|     } | ||||
| } | ||||
| package fr.free.nrw.commons.ui.widget; | ||||
| 
 | ||||
| import android.app.Dialog; | ||||
| import android.graphics.Color; | ||||
| import android.graphics.drawable.ColorDrawable; | ||||
| import android.os.Bundle; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.v4.app.DialogFragment; | ||||
| import android.view.Gravity; | ||||
| import android.view.View; | ||||
| import android.view.Window; | ||||
| import android.view.WindowManager; | ||||
| 
 | ||||
| /** | ||||
|  * a formatted dialog fragment | ||||
|  * This class is used by NearbyInfoDialog | ||||
|  */ | ||||
| public abstract class OverlayDialog extends DialogFragment { | ||||
| 
 | ||||
|     /** | ||||
|      * creates a DialogFragment with the correct style and theme | ||||
|      * @param savedInstanceState | ||||
|      */ | ||||
|     @Override | ||||
|     public void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setStyle(STYLE_NO_FRAME, android.R.style.Theme_Holo_Light); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * When the view is created, sets the dialog layout to full screen | ||||
|      *  | ||||
|      * @param view the view being used | ||||
|      * @param savedInstanceState bundle re-constructed from a previous saved state | ||||
|      */ | ||||
|     @Override | ||||
|     public void onViewCreated(View view, Bundle savedInstanceState) { | ||||
|         setDialogLayoutToFullScreen(); | ||||
|         super.onViewCreated(view, savedInstanceState); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * sets the dialog layout to fullscreen | ||||
|      */ | ||||
|     private void setDialogLayoutToFullScreen() { | ||||
|         Window window = getDialog().getWindow(); | ||||
|         WindowManager.LayoutParams wlp = window.getAttributes(); | ||||
|         window.requestFeature(Window.FEATURE_NO_TITLE); | ||||
|         wlp.gravity = Gravity.BOTTOM; | ||||
|         wlp.width = WindowManager.LayoutParams.MATCH_PARENT; | ||||
|         wlp.height = WindowManager.LayoutParams.MATCH_PARENT; | ||||
|         window.setAttributes(wlp); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * builds custom dialog container | ||||
|      *  | ||||
|      * @param savedInstanceState the previously saved state | ||||
|      * @return the dialog | ||||
|      */ | ||||
|     @NonNull | ||||
|     @Override | ||||
|     public Dialog onCreateDialog(Bundle savedInstanceState) { | ||||
|         Dialog dialog = super.onCreateDialog(savedInstanceState); | ||||
|         Window window = dialog.getWindow(); | ||||
|         window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); | ||||
|         return dialog; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -37,6 +37,13 @@ public class LengthUtils { | |||
|         return computeAngleBetween(from, to) * 6371009.0D; // Earth's radius in meter | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Computes angle between two points | ||||
|      * | ||||
|      * @param from Point A | ||||
|      * @param to   Point B | ||||
|      * @return Angle in radius | ||||
|      */ | ||||
|     private static double computeAngleBetween(LatLng from, LatLng to) { | ||||
|         return distanceRadians(Math.toRadians(from.getLatitude()), | ||||
|                 Math.toRadians(from.getLongitude()), | ||||
|  | @ -44,18 +51,43 @@ public class LengthUtils { | |||
|                 Math.toRadians(to.getLongitude())); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Computes arc length between 2 points | ||||
|      * @param lat1 Latitude of point A | ||||
|      * @param lng1 Longitude of point A | ||||
|      * @param lat2 Latitude of point B | ||||
|      * @param lng2 Longitude of point B | ||||
|      * @return Arc length between the points | ||||
|      */ | ||||
|     private static double distanceRadians(double lat1, double lng1, double lat2, double lng2) { | ||||
|         return arcHav(havDistance(lat1, lat2, lng1 - lng2)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Computes inverse of haversine | ||||
|      * @param x Angle in radian | ||||
|      * @return Inverse of haversine | ||||
|      */ | ||||
|     private static double arcHav(double x) { | ||||
|         return 2.0D * Math.asin(Math.sqrt(x)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Computes distance between two points that are on same Longitude | ||||
|      * @param lat1 Latitude of point A | ||||
|      * @param lat2 Latitude of point B | ||||
|      * @param longitude Longitude on which they lie | ||||
|      * @return Arc length between points | ||||
|      */ | ||||
|     private static double havDistance(double lat1, double lat2, double longitude) { | ||||
|         return hav(lat1 - lat2) + hav(longitude) * Math.cos(lat1) * Math.cos(lat2); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Computes haversine | ||||
|      * @param x Angle in radians | ||||
|      * @return Haversine of x | ||||
|      */ | ||||
|     private static double hav(double x) { | ||||
|         double sinHalf = Math.sin(x * 0.5D); | ||||
|         return sinHalf * sinHalf; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 misaochan
						misaochan