From 8f34c02ab27ce994da416db606014d3c7f061f74 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Wed, 18 Apr 2018 18:32:20 -0300 Subject: [PATCH 01/26] Update AndroidHelper.h --- interface/src/AndroidHelper.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/AndroidHelper.h b/interface/src/AndroidHelper.h index ee1114ce1d..b7bf899356 100644 --- a/interface/src/AndroidHelper.h +++ b/interface/src/AndroidHelper.h @@ -15,7 +15,6 @@ #include #include #include -#include class AndroidHelper : public QObject { Q_OBJECT @@ -48,4 +47,4 @@ private: QThread workerThread; }; -#endif \ No newline at end of file +#endif From 103e9f92fa7fa09138ad61c309450b32424f3628 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Tue, 24 Apr 2018 11:56:01 -0300 Subject: [PATCH 02/26] Add haptic feedback to back, view and mic buttons --- android/app/src/main/cpp/native.cpp | 5 +++++ .../highfidelity/hifiinterface/InterfaceActivity.java | 10 ++++++++++ .../io/highfidelity/hifiinterface/MainActivity.java | 10 ++++++++++ interface/src/AndroidHelper.cpp | 4 ++++ interface/src/AndroidHelper.h | 2 ++ interface/src/Application.cpp | 4 ++++ interface/src/Application.h | 1 + scripts/system/+android/actionbar.js | 3 ++- scripts/system/+android/audio.js | 1 + scripts/system/+android/modes.js | 1 + 10 files changed, 40 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index 3d6c6879b8..ad1f9e4750 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -155,6 +155,11 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCrea QAndroidJniObject string = QAndroidJniObject::fromString(a); __interfaceActivity.callMethod("openGotoActivity", "(Ljava/lang/String;)V", string.object()); }); + + QObject::connect(&AndroidHelper::instance(), &AndroidHelper::hapticFeedbackRequested, [](const QString &c) { + QAndroidJniObject string = QAndroidJniObject::fromString(c); + __interfaceActivity.callMethod("performHapticFeedback", "(Ljava/lang/String;)V", string.object()); + }); } JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnDestroy(JNIEnv* env, jobject obj) { diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index c547fb6ff2..ffc52820c0 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -15,6 +15,7 @@ import android.content.Intent; import android.content.res.AssetManager; import android.net.Uri; import android.os.Bundle; +import android.view.HapticFeedbackConstants; import android.view.WindowManager; import android.util.Log; import org.qtproject.qt5.android.bindings.QtActivity; @@ -218,4 +219,13 @@ public class InterfaceActivity extends QtActivity { super.isLoading = false; } + public void performHapticFeedback(String feedbackConstant) { + switch (feedbackConstant) { + case "CONTEXT_CLICK": + default: + findViewById(android.R.id.content).performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + break; + } + } + } \ No newline at end of file diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java index b2bfadc039..0c15730643 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java @@ -286,4 +286,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On } } + + @Override + public void onBackPressed() { + int index = getFragmentManager().getBackStackEntryCount() - 1; + if (index > -1) { + super.onBackPressed(); + } else { + finishAffinity(); + } + } } diff --git a/interface/src/AndroidHelper.cpp b/interface/src/AndroidHelper.cpp index e187070a73..6dea89b1d0 100644 --- a/interface/src/AndroidHelper.cpp +++ b/interface/src/AndroidHelper.cpp @@ -48,3 +48,7 @@ void AndroidHelper::notifyLoginComplete(bool success) { emit loginComplete(success); } +void AndroidHelper::performHapticFeedback(const QString& feedbackConstant) { + emit hapticFeedbackRequested(feedbackConstant); +} + diff --git a/interface/src/AndroidHelper.h b/interface/src/AndroidHelper.h index 25a7db8c7c..d0a81b8553 100644 --- a/interface/src/AndroidHelper.h +++ b/interface/src/AndroidHelper.h @@ -28,6 +28,7 @@ public: void goBackFromAndroidActivity(); void notifyLoginComplete(bool success); + void performHapticFeedback(const QString& feedbackConstant); QSharedPointer getAccountManager(); @@ -38,6 +39,7 @@ signals: void backFromAndroidActivity(); void qtAppLoadComplete(); void loginComplete(bool success); + void hapticFeedbackRequested(const QString &feedbackConstant); private: AndroidHelper(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b91e3b1e70..8381f43f4a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7950,6 +7950,10 @@ void Application::restoreAfterAndroidActivity() { #endif } +void Application::performHapticFeedback(const QString& feedbackConstant) { + AndroidHelper::instance().performHapticFeedback(feedbackConstant); +} + #if defined(Q_OS_ANDROID) void Application::enterBackground() { qDebug() << "[Background-HIFI] enterBackground begin"; diff --git a/interface/src/Application.h b/interface/src/Application.h index e56474807b..56799875be 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -408,6 +408,7 @@ public slots: Q_INVOKABLE bool askBeforeSetAvatarUrl(const QString& avatarUrl) { return askToSetAvatarUrl(avatarUrl); } Q_INVOKABLE void openAndroidActivity(const QString& activityName); + Q_INVOKABLE void performHapticFeedback(const QString& feedbackConstant); private slots: void onDesktopRootItemCreated(QQuickItem* qmlContext); diff --git a/scripts/system/+android/actionbar.js b/scripts/system/+android/actionbar.js index a1ddc6f2de..dfe3f8bd5b 100644 --- a/scripts/system/+android/actionbar.js +++ b/scripts/system/+android/actionbar.js @@ -38,7 +38,8 @@ function init() { } function onBackPressed() { - App.openAndroidActivity("Goto"); + App.performHapticFeedback("CONTEXT_CLICK"); + App.openAndroidActivity("Goto"); } diff --git a/scripts/system/+android/audio.js b/scripts/system/+android/audio.js index 4d6d8db008..1661c11315 100644 --- a/scripts/system/+android/audio.js +++ b/scripts/system/+android/audio.js @@ -47,6 +47,7 @@ function onMuteClicked() { printd("On Mute Clicked"); //Menu.setIsOptionChecked("Mute Microphone", !Menu.isOptionChecked("Mute Microphone")); Audio.muted = !Audio.muted; + App.performHapticFeedback("CONTEXT_CLICK"); } function onMuteToggled() { diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js index f5b3609c26..3743e1d068 100644 --- a/scripts/system/+android/modes.js +++ b/scripts/system/+android/modes.js @@ -59,6 +59,7 @@ function init() { switchToMode(getCurrentModeSetting()); modeButton.clicked.connect(function() { + App.performHapticFeedback("CONTEXT_CLICK"); switchToMode(nextMode[currentMode]); }); } From 83399e4c6dd6a541df09f6d40585787b463d826d Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Tue, 24 Apr 2018 14:32:38 -0300 Subject: [PATCH 03/26] Fix privacy policy adding a missing (content) file --- .../app/src/main/assets/privacy_policy.html | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 android/app/src/main/assets/privacy_policy.html diff --git a/android/app/src/main/assets/privacy_policy.html b/android/app/src/main/assets/privacy_policy.html new file mode 100644 index 0000000000..f6cdbfcfc7 --- /dev/null +++ b/android/app/src/main/assets/privacy_policy.html @@ -0,0 +1,121 @@ + + +High Fidelity Privacy Policy +
+ +

High Fidelity, Inc. ("High Fidelity") respects the privacy of its online visitors and users of its products and services. We recognize the importance of protecting information collected from our users and have adopted this Privacy Policy to inform you about how we gather, store and use information derived from your use of our products, services and online sites in accordance with local law in the places where we operate. +By using our online sites, products, and services (collectively, the "Service"), you agree that we may collect personally identifiable information (as defined below). We will not share your personally identifiable information except as described herein. +

+1. Types of Information We Collect +

+ We collect two basic types of information - personal information and anonymous information - and we may use personal and anonymous information to create a third type of information, aggregate information. Personal Information means information that identifies (whether directly or indirectly) a particular individual, such as the individual's first and last name, postal address, e-mail address and/or telephone number. Anonymous Information means information that does not directly or indirectly identify, and cannot reasonably be used to identify, an individual (including an individual's computing device). Aggregate Information means information about groups or categories of individuals which does not identify and cannot reasonably be used to identify an individual. We may share Aggregate and Anonymous Information with other parties without restriction. + + We collect the following categories of information: + + Registration information you provide when you create an account, which may include your first name and surname, country of residence, gender, date of birth, e-mail address, username and password. + + Transaction information you provide when you request information or purchase a product or service from us, whether on our sites or through our applications, including your postal address, telephone number and payment information. If you conduct transactions, we may collect and retain some or all of the information related to these transactions, including transaction amount(s), parties involved, time and manner of exchange, and other transaction circumstances. + + Information you provide in public forums on our Service. Please note that our sites and applications may offer chat, forums, community environments (including multiplayer gameplay) or other tools that do not have a restricted audience. If you provide Personal Information when you use any of these features, that Personal Information may be publicly posted and otherwise disclosed without limitation as to its use by us or by a third party. We have no obligation to keep private personally identifiable information that you have made available to other users or the public using these functions. To request removal of your Personal Information from a public forum on one of our sites or applications, please contact Customer Support. + + Information sent either one-to-one or within a limited group using our message, chat, post or similar functionality, where we are permitted by law to collect this information. + + Information you provide to us when you use our sites and applications, our applications on third-party sites or platforms (such as social networking sites), or link your profile from a third-party site or platform to your registered account. + + Location information when you visit our sites or use our applications, including location information either provided by a mobile device interacting with one of our sites or applications, or associated with your IP address, where we are permitted by law to process this information. + + Usage, viewing and technical data, including your device identifier or IP address, when you visit our sites, use our applications on third-party sites or platforms, or open e-mails that we send. + + Additionally there are a few special circumstances to note: + + Intellectual Property Claim Notices: If you notify us of an intellectual property claim, the information in your claim notice may be shared with other parties to the disagreement or third parties in our discretion and as required by law. + + Beta Service User: If you volunteer to serve as a beta participant for our pre-commercial content, we may track bug reports and individual system performance in an effort to test our technology rigorously before it is deployed. + + Former Customer: If you discontinue your use of our Service, we may keep your registration file in our database for use in the event that you elect to renew your use of our Service, as well as for anti-fraud and other such protective measures. + + Job Postings or Unsolicited Communications: Please note that information we receive in reference to a job posting or by unsolicited communications does not fall within the terms outlined in this Privacy Policy, however information from your resume will be used solely for the purpose of evaluating your candidacy for employment. +

+ 2. How We Collect Your Information +

+ + We collect information you provide to us when you request products, services or information from us, register with us, participate in public forums or other activities on our sites and applications, respond to customer inquiries or surveys, or otherwise interact with us. + + We collect information through technology, such as cookies and other technologies (such as web beacons and pixel tags), including when you visit our sites and applications or use our applications on third-party sites or platforms. A cookie is a small string of data which often includes an anonymous unique identifier sent to your Internet browser from a website's computers, which is stored on your computer's hard drive and is used to customize your use of a product or online site, keep records of your access to an online site or product, or store information needed by you on a regular basis (e.g. password retention functionality). High Fidelity (itself or through third parties acting on our behalf) use cookies for a number of purposes relating to our websites, applications and services, including to access your account information where you "login" to our websites, forums or other areas and to keep track of your website session data. You can configure your browser to accept all cookies, reject all cookies, or notify you when a cookie is set. Each browser is different, so consult the "Help" menu of your browser to learn how you change your cookie preferences. Please note that if you reject all cookies, you may not be able to use certain of our (or other companies') web pages. + + We may participate in ad and/or affiliate networks operated by various third party companies. These companies collect and may use certain anonymous information about your visits to our Service as a function of referring Internet traffic to our Service. We do not permit these companies to collect any Personal Information about you; however these companies may collect your IP address. These companies may set and use cookies, web beacons, pixels and other technologies to collect anonymous information about your visits to our Service, and may otherwise aggregate, analyze and anonymize that data. If you would like to learn more about these specialized advertising technologies, the Network Advertising Initiative offers useful information about Internet advertising companies, including information about how to opt-out of certain information collection. + + We acquire information from other trusted sources to update or supplement the information you provided or we collected automatically. Local law may require that you authorize the third party to share your information with us before we can acquire it. +

+ 3. Use of Your Information by High Fidelity +

+ High Fidelity will be the data controller for your information, and will have access to your information for use for the following purposes (unless prohibited by law): + + Provide you with the products and services you request + + Communicate with you about your account or transactions with us and send you information about features on our sites and applications or changes to our policies + + Consistent with local law and choices and controls that may be available to you: + + Send you offers and promotions for our products and services or, as permitted, third-party products and services + + Personalize content and experiences on our sites and applications + + Provide you with advertising based on your activity on our sites and applications and on third-party sites and applications. + Optimize or improve our products, services and operations + + Detect, investigate and prevent activities that may violate our policies or be illegal + + Except under certain limited circumstances as set forth here and in our Terms of Service, High Fidelity does not disclose to third parties the Personal Information or other account-related information that you provide to us without your permission. You understand, however, that High Fidelity may disclose your Personal Information or other account-related information under the following circumstances: + + If we believe in good faith that such disclosure is necessary under applicable law, or to comply with legal process served on High Fidelity; + + In order to protect and defend the rights or interests of High Fidelity, its products and services, and/or the other users of such products and services; + + In order to report to law enforcement authorities, or assist in their investigation of suspected illegal or wrongful activity, or to report any instance in which we believe a person may be in danger; + + To service providers with whom we have contracted to assist us with the features or operations (such as anti-fraud functions, billing, collections, registration, customer support, e-mail delivery, age verification), to fulfill your service requests, offer new content or help us improve our products and/or services. + Our contracts with third parties prohibit them from using any of your Personal Information for purposes unrelated to the product or services they are providing; + + To other third parties (a) to provide you with services you have requested, (b) to offer you information about our products or services (e.g. events or features), or (c) to whom you explicitly ask us to send your information (or about whom you are otherwise explicitly notified and consent to when using a specific service). For instance, we may provide certain information to our payment processor, to credit card associations, banks or issuers (if you are using a credit card), to PayPal (if you are using a PayPal account), or to providers of other services you request. If you choose to use these third parties' products or services, then their use of your information is governed by their privacy policies. You should evaluate the practices of third party providers before deciding to use their services; and + + To other business entities, should we plan to merge with or be acquired by that business entity. +

+ + 4. Sharing Your Information with Other Companies +

+ + We will not share your Personal Information outside of High Fidelity except in limited circumstances, including: + + When you allow us to share your Personal Information with another company, such as: + + Directing us to share your Personal Information with third-party sites or platforms, such as social networking sites + Please note that once we share your Personal Information with another company, the information received by the other company becomes subject to the other company's privacy practices. + + When companies perform services on our behalf; however, these companies are prohibited from using your Personal Information for purposes other than those requested by us or required by law. + + When we share Personal Information with third parties in connection with the sale of a business, to enforce our Terms of Service or rules, to ensure the safety and security of our users and third parties, to comply with legal process or in other cases if we believe in good faith that disclosure is required by law. +

+ 5. Data Transfers, Storage and Processing Globally +

+ + We operate globally and may transfer your Personal Information to locations around the world for the purposes described in this Privacy Policy. Whenever your Personal Information is transferred, stored or processed by us, we will take reasonable steps to safeguard the privacy of your Personal Information in accordance with applicable law. +

+ 6. Changes to this Privacy Policy +

+ + From time to time, we may change this Privacy Policy to accommodate new technologies, industry practices, regulatory requirements or for other purposes. If we decide to change our privacy policy, we will post those changes to this privacy statement, and other places we deem appropriate so that you are aware of what information we collect, how we use it, and under what circumstances, if any, we disclose it. We reserve the right to modify this privacy statement at any time, so please review it frequently. If we make material changes to this policy, we will notify you here, by email, or by means of a notice on our home page. +

+ + 7. Comments and Questions +

+ + If you have a comment or question about this Privacy Policy or our privacy practices, please send an e-mail to privacy@highfidelity.com. +

+
+Notice to California Residents: +

+If you are a California resident, California Civil Code Section 1798.83 permits you to request information regarding the disclosure of your Personal Information by High Fidelity to third parties for the third parties' direct marketing purposes. With respect to these entities, this Privacy Policy applies only to their activities within the State of California. To make such a request, please send an e-mail to privacy@highfidelity.com or write us at the address listed immediately above. +

+ + \ No newline at end of file From 55a946c6c7bfc35903c3ad5425794e69e94b6811 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Tue, 24 Apr 2018 14:48:41 -0300 Subject: [PATCH 04/26] Fix non-android builds(performHapticFeedback) --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eab6986f24..454848c87d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7943,7 +7943,9 @@ void Application::openAndroidActivity(const QString& activityName) { } void Application::performHapticFeedback(const QString& feedbackConstant) { +#if defined(Q_OS_ANDROID) AndroidHelper::instance().performHapticFeedback(feedbackConstant); +#endif } #if defined(Q_OS_ANDROID) From 11d232146774f63cb9373561c31eae2316ffa2f5 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Tue, 24 Apr 2018 16:43:48 -0300 Subject: [PATCH 05/26] New default avatar photo. Support relative url for profile picture. Refactor download profile picture as async task --- .../highfidelity/hifiinterface/HifiUtils.java | 25 +++++++ .../hifiinterface/MainActivity.java | 37 ++-------- .../task/DownloadProfileImageTask.java | 71 +++++++++++++++++++ .../res/drawable/default_profile_avatar.xml | 17 +++++ .../src/main/res/layout/navigation_header.xml | 1 + 5 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/task/DownloadProfileImageTask.java create mode 100644 android/app/src/main/res/drawable/default_profile_avatar.xml diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java b/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java index 15d716548f..408929c20f 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/HifiUtils.java @@ -1,11 +1,16 @@ package io.highfidelity.hifiinterface; +import java.net.URI; +import java.net.URISyntaxException; + /** * Created by Gabriel Calero & Cristian Duarte on 4/13/18. */ public class HifiUtils { + public static final String METAVERSE_BASE_URL = "https://metaverse.highfidelity.com"; + private static HifiUtils instance; private HifiUtils() { @@ -18,6 +23,26 @@ public class HifiUtils { return instance; } + public String absoluteHifiAssetUrl(String urlString) { + return absoluteHifiAssetUrl(urlString, METAVERSE_BASE_URL); + } + + public String absoluteHifiAssetUrl(String urlString, String baseUrl) { + urlString = urlString.trim(); + if (!urlString.isEmpty()) { + URI uri; + try { + uri = new URI(urlString); + } catch (URISyntaxException e) { + return urlString; + } + if (uri.getScheme() == null || uri.getScheme().isEmpty()) { + urlString = baseUrl + urlString; + } + } + return urlString; + } + public native String getCurrentAddress(); } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java index 0c15730643..274ad95347 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java @@ -35,13 +35,14 @@ import io.highfidelity.hifiinterface.fragment.GotoFragment; import io.highfidelity.hifiinterface.fragment.HomeFragment; import io.highfidelity.hifiinterface.fragment.LoginFragment; import io.highfidelity.hifiinterface.fragment.PolicyFragment; +import io.highfidelity.hifiinterface.task.DownloadProfileImageTask; public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, LoginFragment.OnLoginInteractionListener, HomeFragment.OnHomeInteractionListener, GotoFragment.OnGotoInteractionListener { - private static final int PROFILE_PICTURE_PLACEHOLDER = R.drawable.ic_person; + private static final int PROFILE_PICTURE_PLACEHOLDER = R.drawable.default_profile_avatar; private String TAG = "HighFidelity"; public native boolean nativeIsLoggedIn(); @@ -234,36 +235,10 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On * TODO: this should be get from an API (at the moment there is no one for this) */ private void updateProfilePicture(String username) { - Picasso.get().load(PROFILE_PICTURE_PLACEHOLDER).into(mProfilePicture); - - new Thread(() -> { - try { - URL userPage = new URL("https://highfidelity.com/users/" + username); - BufferedReader in = new BufferedReader( - new InputStreamReader( - userPage.openStream())); - - StringBuffer strBuff = new StringBuffer(); - String inputLine; - while ((inputLine = in.readLine()) != null) { - strBuff.append(inputLine); - } - in.close(); - String substr = "img class=\"users-img\" src=\""; - int indexBegin = strBuff.indexOf(substr) + substr.length(); - if (indexBegin >= substr.length()) { - int indexEnd = strBuff.indexOf("\"", indexBegin); - runOnUiThread(() -> { - if (indexEnd > 0) { - Picasso.get().load(strBuff.substring(indexBegin, indexEnd)).into(mProfilePicture, new RoundProfilePictureCallback()); - } - }); - } - } catch (IOException e) { - Log.e(TAG, "Error getting profile picture for username " + username); - } - }).start(); - + mProfilePicture.setImageResource(PROFILE_PICTURE_PLACEHOLDER); + new DownloadProfileImageTask(url -> { if (url!=null && !url.isEmpty()) { + Picasso.get().load(url).into(mProfilePicture, new RoundProfilePictureCallback()); + } } ).execute(username); } public void onPrivacyPolicyClicked(View view) { diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/task/DownloadProfileImageTask.java b/android/app/src/main/java/io/highfidelity/hifiinterface/task/DownloadProfileImageTask.java new file mode 100644 index 0000000000..f32227a31e --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/task/DownloadProfileImageTask.java @@ -0,0 +1,71 @@ +package io.highfidelity.hifiinterface.task; + +import android.os.AsyncTask; +import android.util.Log; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +import io.highfidelity.hifiinterface.HifiUtils; + +/** + * This is a temporary solution until the profile picture URL is + * available in an API + */ +public class DownloadProfileImageTask extends AsyncTask { + + private static final String BASE_PROFILE_URL = "https://highfidelity.com"; + private static final String TAG = "Interface"; + + private final DownloadProfileImageResultProcessor mResultProcessor; + + public interface DownloadProfileImageResultProcessor { + void onResultAvailable(String url); + } + + public DownloadProfileImageTask(DownloadProfileImageResultProcessor resultProcessor) { + mResultProcessor = resultProcessor; + } + + @Override + protected String doInBackground(String... usernames) { + URL userPage = null; + for (String username: usernames) { + try { + userPage = new URL(BASE_PROFILE_URL + "/users/" + username); + BufferedReader in = new BufferedReader( + new InputStreamReader( + userPage.openStream())); + + StringBuffer strBuff = new StringBuffer(); + String inputLine; + while ((inputLine = in.readLine()) != null) { + strBuff.append(inputLine); + } + in.close(); + String substr = "img class=\"users-img\" src=\""; + int indexBegin = strBuff.indexOf(substr) + substr.length(); + if (indexBegin >= substr.length()) { + int indexEnd = strBuff.indexOf("\"", indexBegin); + if (indexEnd > 0) { + String url = strBuff.substring(indexBegin, indexEnd); + return HifiUtils.getInstance().absoluteHifiAssetUrl(url, BASE_PROFILE_URL); + } + } + } catch (IOException e) { + Log.e(TAG, "Error getting profile picture for username " + username); + } + } + return null; + } + + @Override + protected void onPostExecute(String url) { + super.onPostExecute(url); + if (mResultProcessor != null) { + mResultProcessor.onResultAvailable(url); + } + } +} diff --git a/android/app/src/main/res/drawable/default_profile_avatar.xml b/android/app/src/main/res/drawable/default_profile_avatar.xml new file mode 100644 index 0000000000..5db00acdd6 --- /dev/null +++ b/android/app/src/main/res/drawable/default_profile_avatar.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/layout/navigation_header.xml b/android/app/src/main/res/layout/navigation_header.xml index 3ded5a515d..b61e701f48 100644 --- a/android/app/src/main/res/layout/navigation_header.xml +++ b/android/app/src/main/res/layout/navigation_header.xml @@ -9,6 +9,7 @@ android:id="@+id/profilePicture" android:layout_width="64dp" android:layout_height="64dp" + android:src="@drawable/default_profile_avatar" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" android:layout_marginLeft="@dimen/activity_horizontal_margin" From d33855b860d702a002027c5684c79fc6ee2fd719 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Tue, 24 Apr 2018 17:15:05 -0300 Subject: [PATCH 06/26] Advance the haptic feedback from onClick to onPressDown --- scripts/system/+android/actionbar.js | 11 ++++++++--- scripts/system/+android/audio.js | 9 ++++++--- scripts/system/+android/modes.js | 17 ++++++++++++----- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/scripts/system/+android/actionbar.js b/scripts/system/+android/actionbar.js index 368f5b373c..c23ce89d4c 100644 --- a/scripts/system/+android/actionbar.js +++ b/scripts/system/+android/actionbar.js @@ -33,19 +33,24 @@ function init() { hoverBgOpacity: 0.0, activeBgOpacity: 0.0 }); - - backButton.clicked.connect(onBackPressed); + + backButton.entered.connect(onBackPressed); + backButton.clicked.connect(onBackClicked); } function onBackPressed() { App.performHapticFeedback("CONTEXT_CLICK"); +} + +function onBackClicked() { App.openAndroidActivity("Home"); } Script.scriptEnding.connect(function() { if(backButton) { - backButton.clicked.disconnect(onBackPressed); + backButton.entered.disconnect(onBackPressed); + backButton.clicked.disconnect(onBackClicked); } }); diff --git a/scripts/system/+android/audio.js b/scripts/system/+android/audio.js index 1661c11315..5eb13a3198 100644 --- a/scripts/system/+android/audio.js +++ b/scripts/system/+android/audio.js @@ -15,7 +15,7 @@ var audiobar; var audioButton; -var logEnabled = true; +var logEnabled = false; function printd(str) { if (logEnabled) @@ -40,13 +40,15 @@ function init() { onMuteToggled(); audioButton.clicked.connect(onMuteClicked); + audioButton.entered.connect(onMutePressed); Audio.mutedChanged.connect(onMuteToggled); } function onMuteClicked() { - printd("On Mute Clicked"); - //Menu.setIsOptionChecked("Mute Microphone", !Menu.isOptionChecked("Mute Microphone")); Audio.muted = !Audio.muted; +} + +function onMutePressed() { App.performHapticFeedback("CONTEXT_CLICK"); } @@ -59,6 +61,7 @@ function onMuteToggled() { Script.scriptEnding.connect(function () { if(audioButton) { audioButton.clicked.disconnect(onMuteClicked); + audioButton.entered.disconnect(onMutePressed); Audio.mutedChanged.connect(onMuteToggled); } }); diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js index 3743e1d068..c75377b976 100644 --- a/scripts/system/+android/modes.js +++ b/scripts/system/+android/modes.js @@ -57,15 +57,22 @@ function init() { }); switchToMode(getCurrentModeSetting()); - - modeButton.clicked.connect(function() { - App.performHapticFeedback("CONTEXT_CLICK"); - switchToMode(nextMode[currentMode]); - }); + + modeButton.entered.connect(modeButtonPressed); + modeButton.clicked.connect(modeButtonClicked); } function shutdown() { + modeButton.entered.disconnect(modeButtonPressed); + modeButton.clicked.disconnect(modeButtonClicked); +} +function modeButtonPressed() { + App.performHapticFeedback("CONTEXT_CLICK"); +} + +function modeButtonClicked() { + switchToMode(nextMode[currentMode]); } function saveCurrentModeSetting(mode) { From 2673a06d6f083f5899df347742e39e3963193a12 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 25 Apr 2018 17:47:05 -0300 Subject: [PATCH 07/26] Tweak UI (status bar, action bar, privacy policy, login) --- .../hifiinterface/MainActivity.java | 14 +++-- .../app/src/main/res/font/raleway_italic.xml | 7 +++ .../app/src/main/res/layout/activity_main.xml | 5 +- .../src/main/res/layout/fragment_login.xml | 55 +++++++++++-------- .../src/main/res/layout/fragment_policy.xml | 16 +++--- android/app/src/main/res/values/colors.xml | 5 +- android/app/src/main/res/values/dimens.xml | 3 + .../src/main/res/values/preloaded_fonts.xml | 1 + 8 files changed, 64 insertions(+), 42 deletions(-) create mode 100644 android/app/src/main/res/font/raleway_italic.xml diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java index 274ad95347..2298308541 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java @@ -9,6 +9,7 @@ import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; +import android.support.v4.content.ContextCompat; import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.support.v4.view.GravityCompat; @@ -16,21 +17,17 @@ import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.Window; +import android.view.WindowManager; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; - import io.highfidelity.hifiinterface.fragment.GotoFragment; import io.highfidelity.hifiinterface.fragment.HomeFragment; import io.highfidelity.hifiinterface.fragment.LoginFragment; @@ -74,6 +71,11 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On mDrawerLayout = findViewById(R.id.drawer_layout); + Window window = getWindow(); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(ContextCompat.getColor(this, R.color.statusbar_color)); + loadHomeFragment(); } diff --git a/android/app/src/main/res/font/raleway_italic.xml b/android/app/src/main/res/font/raleway_italic.xml new file mode 100644 index 0000000000..6bf9dfa29c --- /dev/null +++ b/android/app/src/main/res/font/raleway_italic.xml @@ -0,0 +1,7 @@ + + + diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index 3401c962b3..31bed89e91 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -16,8 +16,9 @@ android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - android:background="?attr/colorPrimary" - android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" /> + android:background="?attr/colorPrimaryDark" + android:elevation="4dp" + /> + app:srcCompat="@drawable/hifi_header" />