commit 2c9ab0851bf32906666cf59cf7775db44e63e0d9
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Wed Jan 26 12:24:52 2022 +0100

    Downloading updates: dialog progress.

diff --git a/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java b/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java
index 7fa5dc29..6823192b 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogUpdateView.java
@@ -25,20 +25,16 @@ import android.view.View;
 import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import org.distorted.main.R;
 import org.distorted.network.RubikUpdates;
-import org.distorted.objectlib.json.JsonWriter;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class RubikDialogUpdateView
   {
-  private View mView;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
   public RubikDialogUpdateView()
     {
 
@@ -46,45 +42,59 @@ public class RubikDialogUpdateView
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public View createView(Activity act, RubikUpdates.UpdateInfo info, int fontSize, int padding, boolean isNew,
+  public View createView(Activity act, RubikUpdates.UpdateInfo info, int fontSize, int padding,
                          LinearLayout.LayoutParams pImage, LinearLayout.LayoutParams pView,
                          LinearLayout.LayoutParams pText, LinearLayout.LayoutParams pButt )
     {
-    int layoutID = R.layout.dialog_updates_pane;
-    mView = act.getLayoutInflater().inflate(layoutID, null);
+    boolean isCompleted = info.mPercent>=100;
+    int layoutID = isCompleted
+                   ? R.layout.dialog_updates_completed
+                   : R.layout.dialog_updates_started;
 
-    Button button = mView.findViewById(R.id.updates_pane_button);
-
-    button.setOnClickListener( new View.OnClickListener()
-      {
-      @Override
-      public void onClick(View v)
-        {
-        android.util.Log.e("D", "INSTALL pressed");
-        }
-      });
+    View view = act.getLayoutInflater().inflate(layoutID, null);
 
-    TextView title = mView.findViewById(R.id.updates_pane_title);
+    TextView title = view.findViewById(R.id.updates_pane_title);
     title.setText(info.mObjectLongName);
-    TextView description = mView.findViewById(R.id.updates_pane_description);
+    TextView description = view.findViewById(R.id.updates_pane_description);
     description.setText(info.mDescription);
 
-    ImageView image = mView.findViewById(R.id.updates_pane_image);
+    ImageView image = view.findViewById(R.id.updates_pane_image);
     image.setBackgroundResource(R.drawable.unknown_icon);
 
     image.setLayoutParams(pImage);
-    mView.setLayoutParams(pView);
+    view.setLayoutParams(pView);
 
     title.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
     description.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
-    button.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
 
     title.setLayoutParams(pText);
     description.setLayoutParams(pText);
-    button.setLayoutParams(pButt);
 
-    mView.setPadding(padding,padding,padding,padding);
+    view.setPadding(padding,padding,padding,padding);
+
+    if( isCompleted )
+      {
+      Button button = view.findViewById(R.id.updates_pane_button);
+
+      button.setOnClickListener( new View.OnClickListener()
+        {
+        @Override
+        public void onClick(View v)
+          {
+          android.util.Log.e("D", "INSTALL pressed");
+          }
+        });
+
+      button.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+      button.setLayoutParams(pButt);
+      }
+    else
+      {
+      ProgressBar bar = view.findViewById(R.id.updates_pane_bar);
+      bar.setLayoutParams(pButt);
+      bar.setProgress(info.mPercent);
+      }
 
-    return mView;
+    return view;
     }
   }
diff --git a/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java b/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
index 3615e6d0..2b56b4e1 100644
--- a/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
+++ b/src/main/java/org/distorted/dialogs/RubikDialogUpdates.java
@@ -136,13 +136,10 @@ public class RubikDialogUpdates extends AppCompatDialogFragment implements Rubik
 
   private void receiveUpdate(RubikUpdates updates, FragmentActivity act)
     {
-    int numN = updates.getNewNumber();
-    int numU = updates.getUpdNumber();
-    int num = numN+numU;
+    int numC = updates.getCompletedNumber();
 
-    if( num<=0 )
+    if( numC<=0 )
       {
-
       mText.setText(act.getString(R.string.no_updates));
       }
     else
@@ -150,8 +147,8 @@ public class RubikDialogUpdates extends AppCompatDialogFragment implements Rubik
       //mText.setText("Downloading...");
 
       int imagH = (int)(mSize*1.00f);
-      int textH = (int)(mSize*0.23f);
-      int buttH = (int)(mSize*0.49f);
+      int textH = (int)(mSize*0.27f);
+      int buttH = (int)(mSize*0.35f);
 
       LinearLayout.LayoutParams pI = new LinearLayout.LayoutParams( imagH,imagH );
       LinearLayout.LayoutParams pV = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, mSize );
@@ -163,18 +160,21 @@ public class RubikDialogUpdates extends AppCompatDialogFragment implements Rubik
 
       if( mLayout!=null )
         {
-        for(int i=0; i<numN; i++)
+        for(int i=0; i<numC; i++)
           {
-          RubikUpdates.UpdateInfo info = updates.getNewUpdate(i);
+          RubikUpdates.UpdateInfo info = updates.getCompletedUpdate(i);
           RubikDialogUpdateView rubikView = new RubikDialogUpdateView();
-          View pane = rubikView.createView(act,info,mFontSize,mPadding,true,pI,pV,pT,pB);
+          View pane = rubikView.createView(act,info,mFontSize,mPadding,pI,pV,pT,pB);
           mLayout.addView(pane);
           }
-        for(int i=0; i<numU; i++)
+
+        int numS = updates.getStartedNumber();
+
+        for(int i=0; i<numS; i++)
           {
-          RubikUpdates.UpdateInfo info = updates.getUpdUpdate(i);
+          RubikUpdates.UpdateInfo info = updates.getStartedUpdate(i);
           RubikDialogUpdateView rubikView = new RubikDialogUpdateView();
-          View pane = rubikView.createView(act,info,mFontSize,mPadding,false,pI,pV,pT,pB);
+          View pane = rubikView.createView(act,info,mFontSize,mPadding,pI,pV,pT,pB);
           mLayout.addView(pane);
           }
         }
diff --git a/src/main/java/org/distorted/network/RubikUpdates.java b/src/main/java/org/distorted/network/RubikUpdates.java
index 7e15622c..d2cb5ec5 100644
--- a/src/main/java/org/distorted/network/RubikUpdates.java
+++ b/src/main/java/org/distorted/network/RubikUpdates.java
@@ -34,30 +34,33 @@ public class RubikUpdates
     public final String mDescription;
     public final int mObjectMinorVersion;
     public final int mExtrasMinorVersion;
+    public final int mPercent;
     public final boolean mUpdateObject;
     public final boolean mUpdateExtras;
 
-    public UpdateInfo(String shortName, String longName, String description, int objectMinor, int extrasMinor, boolean updateO, boolean updateE)
+    public UpdateInfo(String shortName, String longName, String description, int objectMinor,
+                      int extrasMinor, int percent, boolean updateO, boolean updateE)
       {
       mObjectShortName    = shortName;
       mObjectLongName     = longName;
       mDescription        = description;
       mObjectMinorVersion = objectMinor;
       mExtrasMinorVersion = extrasMinor;
+      mPercent            = percent;
       mUpdateObject       = updateO;
       mUpdateExtras       = updateE;
       }
     }
 
   private String mUrl;
-  private final ArrayList<UpdateInfo> mNew, mUpd;
+  private final ArrayList<UpdateInfo> mCompleted, mStarted;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public RubikUpdates()
     {
-    mNew = new ArrayList<>();
-    mUpd = new ArrayList<>();
+    mCompleted = new ArrayList<>();
+    mStarted   = new ArrayList<>();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -79,39 +82,38 @@ public class RubikUpdates
 
   private void parseLine(String[] elements)
     {
-    String shortName   = elements[0];
-    String objMinor    = elements[1];
-    String extMinor    = elements[2];
-    String longName    = elements[3];
-    String description = elements[4];
-    int oMinor, eMinor;
+    String shortName   = elements[0].trim();
+    String objMinor    = elements[1].trim();
+    String extMinor    = elements[2].trim();
+    String percent     = elements[3].trim();
+    String longName    = elements[4];
+    String description = elements[5];
+    int oMinor, eMinor, oPercent;
 
     try { oMinor = Integer.parseInt(objMinor); }
     catch (NumberFormatException ex) { oMinor = -1; }
     try { eMinor = Integer.parseInt(extMinor); }
     catch (NumberFormatException ex) { eMinor = -1; }
+    try { oPercent = Integer.parseInt(percent); }
+    catch (NumberFormatException ex) { oPercent = -1; }
 
-    if( oMinor>=0 && eMinor>=0 )
+    if( oMinor>=0 && eMinor>=0 && oPercent>=0 )
       {
       int objOrdinal = RubikObjectList.getOrdinal(shortName.toUpperCase());
+      boolean updateO=true, updateE=true;
 
       if( objOrdinal>=0 )
         {
         int localObjectMinor = RubikObjectList.getLocalObjectMinor(objOrdinal);
         int localExtrasMinor = RubikObjectList.getLocalExtrasMinor(objOrdinal);
-        boolean updateO = localObjectMinor<oMinor;
-        boolean updateE = localExtrasMinor<eMinor;
-
-        if( updateO || updateE )
-          {
-          UpdateInfo info = new UpdateInfo(shortName,longName,description,oMinor,eMinor,updateO,updateE);
-          mUpd.add(info);
-          }
+        updateO = localObjectMinor<oMinor;
+        updateE = localExtrasMinor<eMinor;
         }
-      else
+      if( updateO || updateE )
         {
-        UpdateInfo info = new UpdateInfo(shortName,longName,description,oMinor,eMinor,true,true);
-        mNew.add(info);
+        UpdateInfo info = new UpdateInfo(shortName,longName,description,oMinor,eMinor,oPercent,updateO,updateE);
+        if(oPercent>=100) mCompleted.add(info);
+        else              mStarted.add(info);
         }
       }
     }
@@ -122,8 +124,8 @@ public class RubikUpdates
     {
     android.util.Log.e("D", updates);
 
-    mNew.clear();
-    mUpd.clear();
+    mCompleted.clear();
+    mStarted.clear();
 
     String[] lines = updates.split("\n");
     int numLines = lines.length;
@@ -134,7 +136,7 @@ public class RubikUpdates
       for(int line=1; line<numLines; line++)
         {
         String[] elements = lines[line].split(",");
-        if( elements.length>=3 ) parseLine(elements);
+        if( elements.length>=6 ) parseLine(elements);
         }
       }
     }
@@ -143,20 +145,11 @@ public class RubikUpdates
 
   public void updateDone(String shortName)
     {
-    for( UpdateInfo info : mNew)
+    for( UpdateInfo info : mCompleted)
       {
       if( info.mObjectShortName.equals(shortName) )
         {
-        mNew.remove(info);
-        return;
-        }
-      }
-
-    for( UpdateInfo info : mUpd)
-      {
-      if( info.mObjectShortName.equals(shortName) )
-        {
-        mUpd.remove(info);
+        mCompleted.remove(info);
         return;
         }
       }
@@ -164,30 +157,30 @@ public class RubikUpdates
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public UpdateInfo getNewUpdate(int ordinal)
+  public UpdateInfo getCompletedUpdate(int ordinal)
     {
-    return mNew.get(ordinal);
+    return mCompleted.get(ordinal);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public UpdateInfo getUpdUpdate(int ordinal)
+  public UpdateInfo getStartedUpdate(int ordinal)
     {
-    return mUpd.get(ordinal);
+    return mStarted.get(ordinal);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int getNewNumber()
+  public int getCompletedNumber()
     {
-    return mNew.size();
+    return mCompleted.size();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int getUpdNumber()
+  public int getStartedNumber()
     {
-    return mUpd.size();
+    return mStarted.size();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -195,7 +188,7 @@ public class RubikUpdates
   public void showDebug()
     {
     android.util.Log.e("D", "url: "+mUrl);
-    android.util.Log.e("D", "new objects: "+debug(mNew));
-    android.util.Log.e("D", "upd objects: "+debug(mUpd));
+    android.util.Log.e("D", "ready objects: "+debug(mCompleted));
+    android.util.Log.e("D", "next  objects: "+debug(mStarted));
     }
 }
\ No newline at end of file
diff --git a/src/main/java/org/distorted/screens/RubikScreenPlay.java b/src/main/java/org/distorted/screens/RubikScreenPlay.java
index 43614531..5c8bdb7f 100644
--- a/src/main/java/org/distorted/screens/RubikScreenPlay.java
+++ b/src/main/java/org/distorted/screens/RubikScreenPlay.java
@@ -721,9 +721,7 @@ public class RubikScreenPlay extends RubikScreenBase implements RubikNetwork.Upd
         @Override
         public void run()
           {
-          int numN = updates.getNewNumber();
-          int numU = updates.getUpdNumber();
-          int num = numN+numU;
+          int num = updates.getCompletedNumber();
 
           if( num>0 )
             {
diff --git a/src/main/res/drawable/black_progress.xml b/src/main/res/drawable/black_progress.xml
new file mode 100644
index 00000000..764217ce
--- /dev/null
+++ b/src/main/res/drawable/black_progress.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="@android:color/white" />
+        </shape>
+    </item>
+
+    <item android:id="@android:id/progress">
+        <clip>
+            <shape>
+                <solid android:color="@android:color/black" />
+            </shape>
+        </clip>
+    </item>
+
+</layer-list>
+
diff --git a/src/main/res/layout/dialog_updates_completed.xml b/src/main/res/layout/dialog_updates_completed.xml
new file mode 100644
index 00000000..b6ad761a
--- /dev/null
+++ b/src/main/res/layout/dialog_updates_completed.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	android:background="@color/medium_grey"
+	android:padding="8dp"
+	android:orientation="horizontal">
+
+   	<ImageView
+   	    android:id="@+id/updates_pane_image"
+   	    android:scaleType="fitCenter"
+   		android:layout_width="wrap_content"
+   		android:layout_height="wrap_content"/>
+
+   	<LinearLayout
+   		android:layout_width="match_parent"
+ 		android:layout_height="match_parent"
+ 		android:orientation="vertical"
+ 		android:layout_marginStart="8dp">
+
+		<TextView
+    		android:id="@+id/updates_pane_title"
+    		android:gravity="top|start"
+    		android:layout_width="match_parent"
+    		android:layout_height="wrap_content"
+    		android:singleLine="true"
+            android:textStyle="bold"/>
+
+        <TextView
+    		android:id="@+id/updates_pane_description"
+    		android:gravity="top|start"
+    		android:layout_width="match_parent"
+    		android:layout_height="wrap_content"
+    		android:singleLine="true"/>
+
+    	<Button
+             android:id="@+id/updates_pane_button"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:backgroundTint="@color/black"
+             android:minHeight="0dp"
+             android:minWidth="0dp"
+             android:insetTop="0dp"
+             android:insetBottom="0dp"
+             android:text="@string/install"/>
+
+ 	</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/layout/dialog_updates_pane.xml b/src/main/res/layout/dialog_updates_pane.xml
deleted file mode 100644
index 33c3d29f..00000000
--- a/src/main/res/layout/dialog_updates_pane.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-	xmlns:android="http://schemas.android.com/apk/res/android"
-	android:layout_width="match_parent"
-	android:layout_height="wrap_content"
-	android:background="@color/grey"
-	android:padding="8dp"
-	android:orientation="horizontal">
-
-   	<ImageView
-   	    android:id="@+id/updates_pane_image"
-   	    android:scaleType="fitCenter"
-   		android:layout_width="wrap_content"
-   		android:layout_height="wrap_content"/>
-
-   	<LinearLayout
-   		android:layout_width="match_parent"
- 		android:layout_height="match_parent"
- 		android:orientation="vertical"
- 		android:layout_marginStart="8dp"
-
- 		android:layout_gravity="center_vertical">
-
-		<TextView
-    		android:id="@+id/updates_pane_title"
-    		android:gravity="center_vertical"
-    		android:layout_width="match_parent"
-    		android:layout_height="wrap_content"
-    		android:singleLine="true"
-    		android:textStyle="bold"/>
-
-        <TextView
-    		android:id="@+id/updates_pane_description"
-    		android:gravity="center_vertical"
-    		android:layout_width="wrap_content"
-    		android:layout_height="wrap_content"
-    		android:singleLine="true"/>
-
-    	<Button
-             android:id="@+id/updates_pane_button"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:backgroundTint="@color/black"
-             android:text="@string/install"
-             android:gravity="center"/>
-
- 	</LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/layout/dialog_updates_started.xml b/src/main/res/layout/dialog_updates_started.xml
new file mode 100644
index 00000000..548cb543
--- /dev/null
+++ b/src/main/res/layout/dialog_updates_started.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	android:background="@color/medium_grey"
+	android:padding="8dp"
+	android:orientation="horizontal">
+
+   	<ImageView
+   	    android:id="@+id/updates_pane_image"
+   	    android:scaleType="fitCenter"
+   		android:layout_width="wrap_content"
+   		android:layout_height="wrap_content"/>
+
+   	<LinearLayout
+   		android:layout_width="match_parent"
+ 		android:layout_height="match_parent"
+ 		android:orientation="vertical"
+ 		android:layout_marginStart="8dp">
+
+		<TextView
+    		android:id="@+id/updates_pane_title"
+    		android:gravity="top|start"
+    		android:layout_width="match_parent"
+    		android:layout_height="wrap_content"
+    		android:singleLine="true"
+    		android:textStyle="bold"/>
+
+        <TextView
+    		android:id="@+id/updates_pane_description"
+    		android:gravity="top|start"
+    		android:layout_width="wrap_content"
+    		android:layout_height="wrap_content"
+    		android:singleLine="true"/>
+
+    	<ProgressBar
+             android:id="@+id/updates_pane_bar"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             style="@android:style/Widget.ProgressBar.Horizontal"
+             android:progressDrawable="@drawable/black_progress"
+             android:max="100"/>
+
+ 	</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml
index c7874d81..5e781081 100644
--- a/src/main/res/values/colors.xml
+++ b/src/main/res/values/colors.xml
@@ -7,6 +7,7 @@
     <color name="dark_grey">#ff222222</color>
     <color name="grey">#ff333333</color>
     <color name="light_grey">#ff555555</color>
+    <color name="medium_grey">#ff444444</color>
     <color name="black">#ff010101</color>
     <color name="white">#ffffffff</color>
 </resources>
