Skip to content

Commit

Permalink
Merge pull request #85 from learning-layers/integration
Browse files Browse the repository at this point in the history
Release v1.3.5
  • Loading branch information
bqqbarbhg committed Mar 14, 2016
2 parents 0dce5ae + 7172a60 commit 4e83878
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 42 deletions.
9 changes: 8 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ repositories {
maven {
url 'https://raw.github.com/embarkmobile/zxing-android-minimal/mvn-repo/maven-repository/'
}

// For com.github.afollestad.material-dialogs
maven {
url "https://jitpack.io"
}
}

dependencies {
Expand All @@ -52,7 +57,9 @@ dependencies {
compile 'com.android.support:recyclerview-v7:23.0.1'

// Material design dialogs
compile 'com.afollestad:material-dialogs:0.7.9.1'
compile('com.github.afollestad.material-dialogs:commons:0.8.5.4@aar') {
transitive = true
}

// Material design tab strip. Note that this is jpardogo's fork, not the original version
// that's no longer updated. The class name of the view is still same, though.
Expand Down
27 changes: 20 additions & 7 deletions app/src/main/java/fi/aalto/legroup/achso/app/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public final class App extends MultiDexApplication
public static VideoInfoRepository videoInfoRepository;

public static File localStorageDirectory;
public static File cacheVideoDirectoryBase;

public static AchRailsStrategy achRails;

private static Uri layersBoxUrl;
private static Uri publicLayersBoxUrl;
Expand Down Expand Up @@ -101,22 +104,22 @@ public void onCreate() {
Toast.makeText(this, R.string.storage_error, Toast.LENGTH_LONG).show();
}

File cacheVideoDirectory = new File(localStorageDirectory, "cache");
cacheVideoDirectory.mkdirs();
cacheVideoDirectoryBase = new File(localStorageDirectory, "cache");
cacheVideoDirectoryBase.mkdirs();

if (!cacheVideoDirectory.isDirectory()) {
if (!cacheVideoDirectoryBase.isDirectory()) {
// If the cache directory can't be created use internal App storage
// There is a slim chance that the user saves some modified videos to the internal
// storage and then inserts and SD card causing videos not to be uploaded, but it
// doesn't seem worth the trouble.

File internalDataDirectory = new File(getApplicationInfo().dataDir);
cacheVideoDirectory = new File(internalDataDirectory, "manifestcache");
cacheVideoDirectory.mkdirs();
cacheVideoDirectoryBase = new File(internalDataDirectory, "manifestcache");
cacheVideoDirectoryBase.mkdirs();
}

combinedRepository = new CombinedVideoRepository(bus, jsonSerializer,
localStorageDirectory, cacheVideoDirectory);
localStorageDirectory, makeCacheVideoDirectory());

videoRepository = combinedRepository;
videoInfoRepository = combinedRepository;
Expand All @@ -139,6 +142,14 @@ public void onCreate() {
AppAnalytics.setup(this);
}

public static File makeCacheVideoDirectory() {
String host = getLayersBoxUrl().getHost().replace('.', '_');
File path = new File(cacheVideoDirectoryBase, host);
path.mkdirs();

return path;
}

public static void updateOIDCTokens(final Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);

Expand Down Expand Up @@ -239,7 +250,9 @@ public static void setupUploaders(Context context) {
combinedRepository.clear();
UploadService.clearUploaders();

combinedRepository.addHost(new AchRailsStrategy(jsonSerializer, getAchRailsUrl(context)));
achRails = new AchRailsStrategy(jsonSerializer, getAchRailsUrl(context));
combinedRepository.addHost(achRails);
combinedRepository.setCacheRoot(makeCacheVideoDirectory());

// Temporary uploader until ClViTra2 is fixed in the Layers Box
// TODO: Remove this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ private void doLogin() {
AccountManager accountManager = AccountManager.get(this);
String accountType = Authenticator.ACH_SO_ACCOUNT_TYPE;

// Next sync after logging in is important.
App.videoRepository.forceNextSyncImportant();

final Account availableAccounts[] = accountManager.getAccountsByType(accountType);

if (availableAccounts.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public void logoutExplicitly() {
*/
public void logout() {
setState(LoginState.LOGGED_OUT, true);
account = null;
user = null;
}

public LoginState getState() {
Expand Down
105 changes: 86 additions & 19 deletions app/src/main/java/fi/aalto/legroup/achso/browsing/BrowserActivity.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package fi.aalto.legroup.achso.browsing;

import android.Manifest;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.SearchManager;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
Expand All @@ -23,6 +26,8 @@
import android.view.View;
import android.view.animation.DecelerateInterpolator;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.astuetz.PagerSlidingTabStrip;
import com.melnykov.fab.FloatingActionButton;
import com.melnykov.fab.ScrollDirectionListener;
Expand All @@ -39,6 +44,7 @@

import fi.aalto.legroup.achso.R;
import fi.aalto.legroup.achso.app.App;
import fi.aalto.legroup.achso.app.AppPreferences;
import fi.aalto.legroup.achso.authentication.LoginActivity;
import fi.aalto.legroup.achso.authentication.LoginErrorEvent;
import fi.aalto.legroup.achso.authentication.LoginRequestEvent;
Expand Down Expand Up @@ -70,8 +76,10 @@ public final class BrowserActivity extends BaseActivity implements View.OnClickL

private static final int ACH_SO_TAKE_VIDEO_PERM = 3;
private static final int ACH_SO_LOG_IN_PERM = 4;
private static final int ACH_SO_BROWSE_PERM = 5;

private static final String STATE_VIDEO_BUILDER = "STATE_VIDEO_BUILDER";
private static final String ARG_LAYERS_BOX_URL = "ARG_LAYERS_BOX_URL";

private Bus bus;

Expand Down Expand Up @@ -99,6 +107,25 @@ protected void onCreate(Bundle savedInstanceState) {
videoBuilder = savedInstanceState.getParcelable(STATE_VIDEO_BUILDER);
}

// Try to parse the Layers Box URL from the intent
Intent intent = getIntent();
if (intent != null) {
String intentLayersBoxUrlString = intent.getStringExtra(ARG_LAYERS_BOX_URL);
if (intentLayersBoxUrlString != null) {
Uri intentLayersBoxUrl = Uri.parse(intentLayersBoxUrlString);
if (intentLayersBoxUrl != null && !intentLayersBoxUrl.equals(App.getLayersBoxUrl())) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
preferences.edit()
.putString(AppPreferences.LAYERS_BOX_URL, intentLayersBoxUrl.toString())
.putBoolean(AppPreferences.USE_PUBLIC_LAYERS_BOX, false)
.apply();

bus.post(new LoginRequestEvent(LoginRequestEvent.Type.EXPLICIT_LOGOUT));
OIDCConfig.setTokens(null, null);
}
}
}

this.tabAdapter = new VideoTabAdapter(this, getSupportFragmentManager());
this.tabAdapter.notifyDataSetChanged();

Expand All @@ -123,6 +150,12 @@ protected void onCreate(Bundle savedInstanceState) {

// Control the media volume instead of the ringer volume
setVolumeControlStream(AudioManager.STREAM_MUSIC);

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
}, ACH_SO_BROWSE_PERM);
}
}

@Override
Expand Down Expand Up @@ -424,6 +457,10 @@ public void onLoginState(LoginStateEvent event) {
}
}


swipeRefreshLayout.setRefreshing(true);
SyncService.syncWithCloudStorage(this);

invalidateOptionsMenu();
}

Expand Down Expand Up @@ -496,32 +533,62 @@ public void onRequestPermissionsResult(int requestCode, String permissions[], in
// We need all three permissions (Fine location, using the camera, writing to the filesystem
// Otherwise we just show a toast and exit.
if (requestCode == ACH_SO_TAKE_VIDEO_PERM) {
if (grantResults.length == 4) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
showSnackbar(R.string.video_no_permissions);
return;
}
}
recordVideo();
} else {
showSnackbar(R.string.video_no_permissions);
}
if (!checkPermissions(R.string.video_no_permissions, permissions, grantResults))
return;

recordVideo();

} else if (requestCode == ACH_SO_LOG_IN_PERM) {
if (grantResults.length != 2)
if (!checkPermissions(R.string.log_in_no_permissions, permissions, grantResults))
return;
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
showSnackbar(R.string.video_no_permissions);
return;
}
}

Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
} else if (requestCode == ACH_SO_BROWSE_PERM) {
if (!checkPermissions(R.string.browse_no_permissions, permissions, grantResults))
return;

SyncService.syncWithCloudStorage(this);
}
}

private boolean checkPermissions(int messageResource, String permissions[], int[] grantResults) {
boolean hasPermissions = true;

if (permissions.length == grantResults.length) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
hasPermissions = false;
break;
}
}
} else {
hasPermissions = false;
}

if (!hasPermissions) {

MaterialDialog dialog = new MaterialDialog.Builder(this)
.title(messageResource)
.negativeText(R.string.cancel)
.positiveText(R.string.go_to_settings)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(MaterialDialog dialog, DialogAction which) {
Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);
myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(myAppSettings);
}
})
.build();
dialog.show();

}

return hasPermissions;
}

/**
* This class listens for the VideoRepositoryUpdatedEvent and tells if one has been received.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import com.google.common.base.Objects;

import java.util.Date;

import fi.aalto.legroup.achso.entities.serialization.json.JsonSerializable;

/**
Expand All @@ -17,16 +19,19 @@ public class Annotation implements JsonSerializable, Parcelable {
protected PointF position;
protected String text;
protected User author;
protected Date createdTimestamp;

Annotation() {
// For serialization and pooling
createdTimestamp = new Date();
}

public Annotation(long time, PointF position, String text, User author) {
public Annotation(long time, PointF position, String text, User author, Date createdTimestamp) {
this.time = time;
this.position = position;
this.text = text;
this.author = author;
this.createdTimestamp = createdTimestamp;
}

protected Annotation(Parcel parcel) {
Expand Down Expand Up @@ -78,6 +83,14 @@ public void setAuthor(User author) {
this.author = author;
}

public Date getCreatedTimestamp() {
return createdTimestamp;
}

public void setCreatedTimestamp(Date createdTimestamp) {
this.createdTimestamp = createdTimestamp;
}

@Override
public int describeContents() {
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class OptimizedVideo {
private float[] annotationXY;
private int[] annotationTextStartEnd;
private int[] annotationAuthorUserIndex;
private long[] annotationCreatedTimestampInMs;
private long lastModified;
private int formatVersion;

Expand Down Expand Up @@ -239,6 +240,7 @@ public OptimizedVideo(Video video) {
annotationXY = new float[annotationCount * 2];
annotationTextStartEnd = new int[annotationCount * 2];
annotationAuthorUserIndex = new int[annotationCount];
annotationCreatedTimestampInMs = new long[annotationCount];

// This buffer will contain all the annotation text data
// The single annotation texts are just substrings of this
Expand Down Expand Up @@ -279,6 +281,9 @@ public OptimizedVideo(Video video) {

// Intern the user and store as index so we don't have so much object references
annotationAuthorUserIndex[i] = UserPool.internUser(annotation.getAuthor());

// Store Date objects as long (They internally are just wrapped long)
annotationCreatedTimestampInMs[i] = annotation.getCreatedTimestamp().getTime();
}

annotationTextBuffer = annotationBufferBuilder.toString();
Expand Down Expand Up @@ -368,6 +373,9 @@ public Video inflate(PooledVideo pooled) {

// Retrieve the interned user with the index.
annotation.setAuthor(UserPool.getInternedUser(annotationAuthorUserIndex[i]));

// Create the Date objects from the longs1
annotation.setCreatedTimestamp(new Date(annotationCreatedTimestampInMs[i]));
}

return video;
Expand Down
Loading

0 comments on commit 4e83878

Please sign in to comment.